Skip to content

Add emoji reactions (limited set on notes) - #76767

Open
adamsilverstein wants to merge 196 commits into
trunkfrom
add-notes-emoji-reactions-try-addditional-comment-type
Open

adamsilverstein wants to merge 196 commits into
trunkfrom
add-notes-emoji-reactions-try-addditional-comment-type

Conversation

@adamsilverstein

@adamsilverstein adamsilverstein commented Mar 23, 2026 •

Copy link
Copy Markdown
Member

Summary

Closes #75144

Adds the foundation for emoji reactions on block notes. This PR is scoped to a small curated 5-emoji quick row (heart, celebration, smile, eyes, rocket). The full searchable emoji picker behind a + button lives in a follow-up PR stacked on this one - per @t-hamano's request, so library/bundling decisions can be reviewed separately.

Storage: reactions as a custom comment type

Reactions are stored as individual reaction comment records (one per user-emoji-note triple), as suggested by @swissspidy, in preference to JSON blobs in comment meta:

comment_type    = 'reaction'
comment_parent  = <note ID>
comment_content = <emoji slug>             // e.g. 'heart'
user_id         = <reacting user>

This is more flexible, aligns with WordPress data patterns (similar to the React plugin), and could eventually extend to regular comments. The custom type is hidden from wp-admin/edit-comments.php and excluded from comment counts.

Curated emoji set

The default 5 emojis (heart, celebration, smile, eyes, rocket) are stored as ASCII slugs (e.g. heart). Storing slugs sidesteps utf8 vs utf8mb4 portability issues on the comments table and gives stable grouping in the reaction_summary aggregation.

The list is filterable via the gutenberg_note_reaction_emojis PHP filter and exposed to clients through the REST API schema (reaction_emojis property on OPTIONS /wp/v2/comments), implementing the approach suggested by @Mamaduka.

Efficient reaction loading

Each note response includes a reaction_summary field - { [emojiSlug]: { count, reacted, my_reaction_id } }. The schema lives in class-gutenberg-rest-comment-controller-7-1.php, populated in prepare_item_for_response().

  • No N+1: get_items() pre-fetches summaries for the entire result set with one aggregated GROUP BY query plus one query for the current user's own reactions, regardless of how many notes are returned (see prefetch_reaction_summaries()).
  • Lazy-loaded reactor names: who reacted is not embedded in reaction_summary - names are fetched on tooltip hover, so the initial notes load stays cheap.

Popover architecture

The curated picker uses @wordpress/components/Dropdown, whose Popover portals to <body>. This is essential because the collab sidebar has an overflow: hidden chain reaching all the way up to .interface-interface-skeleton__sidebar (framework-level); a non-portaled popover would clip. The note thread's onBlur handler exempts .components-popover so that focus moving into the picker doesn't deselect the note (which would unmount the trigger and close the picker mid-click).

Where the trigger lives

The 😊 trigger floats in the note's top corner, in the same column as Resolve and the actions menu, and stays faded until the note is hovered or the trigger itself is focused. A note nobody has reacted to costs no vertical space for the option, and the note text keeps a safe area on that side so it never runs underneath. Once a reaction lands the row drops into the flow, and the trigger trails the pills and wraps with them. This follows @annezazu's suggestion and @fcoveram's exploration, and was first built in #82313 on the follow-up PR before moving here per @draganescu's question.

  • The reveal hangs off the note and the trigger, not the thread. The thread is tabIndex={ 0 }, so a thread-level :focus-within would hold for as long as the note is selected, and a thread-level :hover would reveal the trigger on every note in the thread at once.
  • The whole treatment sits inside @media (hover: hover), so a touch device keeps a trigger it can actually see.
  • Pills no longer disappear when a note is deselected. Reactions are information about the note rather than one of its actions.
  • Pill treatment follows the Notes emoji reaction Figma: your own reaction is a transparent pill with the brand outline, other people's are quiet neutral text, and the trigger is a minimal icon button - all Design System Button variants, no custom CSS.

Related

Remaining feedback from #75549

  • Unbounded reaction requests (@ellatrix) - useEntityRecords for reactions has no per_page limit. Consider lazy-loading reactions only when a note thread is opened. Comment
  • Move emoji SVG icons to @wordpress/icons (@ellatrix) - Low priority, fine for now. Comment
  • Reaction embedding (@Mamaduka) - Reactions could be an embeddable resource on each note to reduce the number of requests. Comment
  • Performance at scale (@Mamaduka) - Consider how reactions perform with thousands of comments (e.g. make.wordpress.org). Comment

Already addressed

  • Move PHP code to wordpress-7.1 compat dir (@Mamaduka, @t-hamano) - Done
  • Rename comment type to reaction (@swissspidy) - Done
  • Emoji extensibility / filtering (@Mamaduka, @youknowriad, @aaronjorbin) - gutenberg_note_reaction_emojis filter, surfaced via REST schema
  • Re-add reaction after removing - Fixed both server-side (status='approve' duplicate guard) and client-side (force-delete + parent-note refetch); regression-guarded by E2E test
  • Full picker scope (@t-hamano) - Moved to a follow-up PR stacked on this one

Screenshots

At rest Hovered Picker open
A note with no reactions and no visible trigger Hovering the note reveals the smiley trigger in its top corner The curated five-emoji picker open beside the note
Your reactions and someone else's Deselected
An eyes reaction from another user with a quiet pill and tooltip, next to the current user's heart and rocket in the blue outline, with the trigger trailing them A deselected note keeps its reaction pills and hides the trigger

Screencast

Hover to reveal the trigger, react twice, then deselect the note:

Screencast: hovering a note reveals the add-reaction trigger, picking a heart and a rocket adds pills that the trigger trails, and deselecting the note keeps the pills

Testing

Test in WordPress Playground

For testing with multiple users, use the User Switching Plugin - https://wordpress.org/plugins/user-switching/

  • Create a note on a block
  • Move the pointer away from the sidebar - the 😊 trigger is hidden, and the note is no taller for carrying it
  • Hover the note - the trigger fades in at the note's top right corner, in the same column as Resolve and the actions menu
  • Add a reply, then hover one note in the thread - only that note reveals its trigger
  • Tab to the trigger with the keyboard - it appears as focus lands on it
  • Click 😊 - pick from the curated 5-emoji row; the trigger now trails the pill
  • Move the pointer away from the note - with reactions on it, the trigger stays visible at the end of the pills
  • Pick the same emoji twice - verify reaction count goes up, not a duplicate
  • Remove a reaction by clicking its pill, then add the same emoji back - verify it works (regression for the trash-counts-as-duplicate bug)
  • Add multiple different emojis to the same note
  • Hover a reaction pill - verify the tooltip shows the reactor names
  • Verify your own reaction takes the blue outline, and someone else's stays quiet with no border or fill
  • Click the post title to deselect the note - the pills stay, the trigger goes
  • Verify the popover doesn't get clipped by the pinned "All notes" sidebar's overflow
  • Check wp-admin comments page doesn't show reaction comments
  • Check comment counts aren't inflated by reactions
  • Verify keyboard accessibility: Enter on smiley opens picker, ArrowDown/ArrowUp navigates, Enter selects, Escape closes
  • Run E2E tests: npm run test:e2e -- test/e2e/specs/editor/various/block-notes.spec.js
  • Run PHP tests: npm run test:unit:php:base -- --filter=Gutenberg_REST_Comments

AI Use

Code and description both written with 🤖 Claude Code, with plenty of steering. I will review and test.

@github-actions github-actions Bot added the [Package] Editor /packages/editor label Mar 23, 2026
@adamsilverstein adamsilverstein added [Type] Enhancement A suggestion for improvement. [Feature] Notes Phase 3 of the Gutenberg roadmap around block commenting [Status] In Progress Tracking issues with work in progress and removed [Package] Editor /packages/editor labels Mar 23, 2026
@github-actions github-actions Bot added the [Package] Editor /packages/editor label Mar 23, 2026
@github-actions

github-actions Bot commented Mar 23, 2026 •

Copy link
Copy Markdown

Size Change: +2.71 kB (+0.03%)

Total Size: 7.92 MB

📦 View Changed
Filename Size Change
build/scripts/editor/index.min.js 583 kB +2.22 kB (+0.38%)
build/styles/editor/style-rtl.css 31.7 kB +123 B (+0.39%)
build/styles/editor/style-rtl.min.css 27.2 kB +123 B (+0.45%)
build/styles/editor/style.css 31.8 kB +121 B (+0.38%)
build/styles/editor/style.min.css 27.2 kB +123 B (+0.46%)

compressed-size-action

@github-actions

github-actions Bot commented Mar 23, 2026 •

Copy link
Copy Markdown

Flaky tests detected in 4b59106.
Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/33358611256
📝 Reported tests:

As a user I expect my navigation to use the colors I selected for it in /test/e2e/specs/editor/blocks/navigation-colors.spec.js, passed after 1 failed attempt.
Error: apiRequestContext.fetch: socket hang up
Call log:
  - → GET http://localhost:8889/wp-json/wp/v2/pages?per_page=100&status=publish%2Cfuture%2Cdraft%2Cpending%2Cprivate%2Ctrash
    - user-agent: Playwright/1.62.1 (x64; ubuntu 24.04) node/20.20 CI/1
    - accept: */*
    - accept-encoding: gzip,deflate,br
    - X-WP-Nonce: 2f3c77dfcc
    - cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_23778236db82f19306f247e20a353a99=admin%7C1788325109%7CVDQVpdmKyGDyJHhldNDkxBbMUjRgNfY7pfKdaQevpAB%7Cf13d914b590c5dcad536a59c54d71fbbb03092cab588316d1ce200012f9c2165; wp-settings-time-1=1788152342

    at RequestUtils.rest (/home/runner/work/gutenberg/gutenberg/packages/e2e-test-utils-playwright/src/request-utils/rest.ts:112:39)
    at RequestUtils.deleteAllPages (/home/runner/work/gutenberg/gutenberg/packages/e2e-test-utils-playwright/src/request-utils/pages.ts:44:27)
    at /home/runner/work/gutenberg/gutenberg/test/e2e/specs/editor/blocks/navigation-colors.spec.js:38:17

@swissspidy

Copy link
Copy Markdown
Member

Regarding unbounded requests & embedding reactions:

If embedding all the reactions on a given note is too much, we could think about caching/retrieving only the reaction count (grouped by emoji). This way we can quickly display the different reactions on a note and lazy load the individual reactions (and who gave them) after that.

@github-actions github-actions Bot added the [Package] Icons /packages/icons label Apr 4, 2026
@adamsilverstein adamsilverstein changed the title Notes: Store emoji reactions as custom comment type Notes: Add emoji reactions - stored as custom comment type Apr 29, 2026
@adamsilverstein

adamsilverstein commented Apr 29, 2026 •

Copy link
Copy Markdown
Member Author

Two open threads carried over from #75549 worth noting:

  1. Notes query is still unbounded (hooks.js:39 uses per_page: -1). reaction_summary solved the per-reaction fan-out, but Mamaduka's scale concern about thousands of notes (e.g. make.wordpress.org blogs) is still open. Probably a follow-up rather than a blocker, but flagging.
  2. Storage decision (custom comment type vs. meta) was settled across #75148 and #75549 but isn't documented here. Linking the rationale in the PR description would save a future reviewer from relitigating it.

All other feedback from #75549 has been addressed — see my comparison for details.

@adamsilverstein
adamsilverstein requested review from Mamaduka and t-hamano and removed request for spacedmonkey April 29, 2026 03:01
@adamsilverstein
adamsilverstein marked this pull request as draft April 29, 2026 03:01
@adamsilverstein

adamsilverstein commented Apr 29, 2026 •

Copy link
Copy Markdown
Member Author

@swissspidy this is what's shipping now - in case you want to double-check it matches what you had in mind:

  • Counts grouped by emoji: each note response includes a reaction_summary field — { [emojiSlug]: { count, reacted, my_reaction_id } }. Schema in class-gutenberg-rest-comment-controller-7-1.php:54, populated in prepare_item_for_response().
  • No N+1: get_items() pre-fetches summaries for the entire result set with one aggregated GROUP BY query plus one query for the current user's own reactions, regardless of how many notes are returned (see prefetch_reaction_summaries()).
  • Lazy-loaded reactor names: who reacted is not in reaction_summary — names are fetched on tooltip hover (commit 776efb9bc00), so the initial notes load stays cheap.

The unbounded per_page: -1 on the notes query itself is still open — that's a separate concern about how many notes we load at once, not how reactions are loaded per note.

@adamsilverstein

Copy link
Copy Markdown
Member Author

I'm going to look at leveraging an existing library for the emoji picker itself, something like https://github.com/liveblocks/frimousse that is well maintained, license compatible and designed to be styled/extended. This would provide a much richer experience, and we can still start with the simplified design of a small set of emoji with the full selection "behind" a (+) plus button.

@adamsilverstein

Copy link
Copy Markdown
Member Author

Here is a screencast of the current implementation in action:

react.with.emoji.picker.mp4

@adamsilverstein
adamsilverstein marked this pull request as ready for review May 8, 2026 00:13
@adamsilverstein
adamsilverstein requested review from aaronjorbin and removed request for ajitbohra, nerrad and ntwb May 8, 2026 00:13
adamsilverstein and others added 7 commits October 7, 2026 16:20
Co-authored-by: Aki Hamano <54422211+t-hamano@users.noreply.github.com>
…tions-try-addditional-comment-type

# Conflicts:
#	packages/editor/CHANGELOG.md
Reviewers on the matching core change prefer not to define what counts
as an "internal" comment type before a custom comment types API exists,
since reactions may later apply to public comments too. Drop the
gutenberg_get_internal_comment_types() helper and its filter, and list
'note' and 'reaction' at each call site.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01THCU4aj11hnJP5ZbUegTRh
…on-display.tsx

Co-authored-by: Aki Hamano <54422211+t-hamano@users.noreply.github.com>
The picker now uses checkbox items so users can see which emoji they
already reacted with. On a resolved thread the add-reaction trigger was
shown disabled on some notes and hidden until hover on others; hiding it
entirely removes that inconsistency, since reactions can't be toggled
there anyway.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01THCU4aj11hnJP5ZbUegTRh
The pill's accessible label already formats the count for the user's
locale, so the visible number should match.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01THCU4aj11hnJP5ZbUegTRh
…dditional-comment-type' into add-notes-emoji-reactions-try-addditional-comment-type
adamsilverstein added a commit that referenced this pull request Oct 7, 2026
Reviewers on the matching core change prefer not to define what counts
as an "internal" comment type before a custom comment types API exists,
since reactions may later apply to public comments too. Drop the
gutenberg_get_internal_comment_types() helper and its filter, and list
'note' and 'reaction' at each call site, as on #76767.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01THCU4aj11hnJP5ZbUegTRh
adamsilverstein added a commit that referenced this pull request Oct 7, 2026
Format the count for the user's locale in both the pill and its
accessible label, as on #76767.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01THCU4aj11hnJP5ZbUegTRh
adamsilverstein and others added 4 commits October 7, 2026 23:55
The trashed and resolved checks ran before the same-post check, so a user
who can edit one post could pass a note ID from another post and learn
from the error whether that note was trashed or resolved. Check the post
first so a note elsewhere always gets the same error.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017a8BrMHjzF5oUjpCyXWoRu
…tions-try-addditional-comment-type

# Conflicts:
#	packages/editor/CHANGELOG.md
#	packages/editor/src/components/collab-sidebar/README.md
The core backport picked up review fixes the plugin controller lacked:
reactions can only be created approved and skip the status handler, the
reaction key is trimmed before validation, a note whose only children
are reactions no longer advertises a children link, and the collection
permission check follows core's handling of post types without notes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013G96dwN6H2B8pDSyrryfd5
Core's backport excludes reactions unless 'all' or 'reaction' is asked
for via type or type__in, and keeps notes and reactions out of
get_lastcommentmodified(). The plugin only excluded them when no type
was set and never touched the last modified lookup. Reaction IDs are
also returned oldest first, matching wp_get_note_reaction_ids().

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013G96dwN6H2B8pDSyrryfd5
*
* @since 7.2.0
*
* @return array Item schema data.

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.

Suggested change
* @return array Item schema data.
* @return array<string, mixed> Item schema data.

'type' => 'object',
'context' => array( 'view', 'edit' ),
'readonly' => true,
'additionalProperties' => array(

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.

It's not clear to me why additionalProperties is used here. Couldn't it enumerate the emoji for each property explicitly? Maybe not if it is unbounded.

'properties' => array(
'count' => array(
'description' => __( 'Total number of reactions with this emoji.', 'gutenberg' ),
'type' => 'integer',

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.

Suggested change
'type' => 'integer',
'type' => 'integer',
'minimum' => 0,

),
'current_user_reaction' => array(
'description' => __( 'The current user\'s reaction comment ID for this emoji, or 0 if they have not reacted.', 'gutenberg' ),
'type' => 'integer',

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.

Suggested change
'type' => 'integer',
'type' => 'integer',
'minimum' => 0,

* @param string $type The comment type from the request.
* @return bool True if the type is one of the internal comment types.
*/
protected function is_note_or_reaction( $type ) {

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.

Suggested change
protected function is_note_or_reaction( $type ) {
protected function is_note_or_reaction( ?string $type ): bool {

$new_count = (int) $wpdb->get_var(
$wpdb->prepare(
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
"SELECT COUNT(*) FROM $wpdb->comments WHERE comment_post_ID = %d AND comment_approved = '1' AND comment_type NOT IN ( $type_placeholders )",

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.

No need to use $type_placeholders here. The $internal_types is an array of string literals which can be used in the SQL directly.

* includes trashed reactions.
* @return int[] Reaction comment IDs, oldest first.
*/
function gutenberg_get_note_reaction_ids( $note, $status = 'any' ) {

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.

Suggested change
function gutenberg_get_note_reaction_ids( $note, $status = 'any' ) {
function gutenberg_get_note_reaction_ids( WP_Comment $note, string $status = 'any' ): array {

* @param string $comment_id The comment ID as a numeric string.
* @param WP_Comment $comment The comment being deleted.
*/
function gutenberg_delete_note_reactions( $comment_id, $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.

Suggested change
function gutenberg_delete_note_reactions( $comment_id, $comment ) {
function gutenberg_delete_note_reactions( $comment_id, WP_Comment $comment ): void {

* @since 7.2.0
*
* @param string $comment_id The comment ID as a numeric string.
* @param WP_Comment $comment The comment being deleted.

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.

Suggested change
* @param WP_Comment $comment The comment being deleted.
* @param WP_Comment $comment The comment being deleted.
*
* @phpstan-param numeric-string $comment_id

Comment on lines +280 to +283
* @param string $comment_id The comment ID as a numeric string.
* @param WP_Comment $comment The trashed comment.
*/
function gutenberg_trash_note_reactions( $comment_id, $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.

Suggested change
* @param string $comment_id The comment ID as a numeric string.
* @param WP_Comment $comment The trashed comment.
*/
function gutenberg_trash_note_reactions( $comment_id, $comment ) {
* @param string $comment_id The comment ID as a numeric string.
* @param WP_Comment $comment The trashed comment.
*
* @phpstan-param numeric-string $comment_id
*/
function gutenberg_trash_note_reactions( $comment_id, WP_Comment $comment ): void {

- useNoteReactions( noteId ): useEntityProp-style [ summary, toggle ].
- Drop redundant summary refetch; notes list refetch already brings it.
- Merge pills and picker into NoteReactions.
- Reactor names tied to summary identity; drop module cache.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Mamaduka

Mamaduka commented Oct 9, 2026 •

Copy link
Copy Markdown
Member

Pushed a cleanup commit for the reactions JS; no user-visible change.

Each toggle was sending three requests: the reaction save/delete, a _fields refetch of reaction_summary, and a full notes list refetch, since core-data invalidates every root/comment query on save and delete. The list refetch already returns the authoritative summary, so the extra refetch and its mutation counter are gone. applyReactionDelta covers the gap until the list lands.

  • useNoteReactions( noteId ) replaces useReaction and works like useEntityProp: returns [ summary, toggleReaction ].
  • NoteReactions replaces ReactionDisplay and AddReactionButton, so Note renders a single component.
  • Reactor names are tied to the summary they were fetched for, which removes the module-level cache and invalidateReactionNames.
  • Unit tests now cover only applyReactionDelta; the aria-pressed check moved to e2e.

Follow-ups, not blocking:

Replace the hand-rolled page walk and names cache with a getEntityRecords
select gated on pill hover/focus. core-data caches across remounts and
invalidates on comment writes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Mamaduka

Mamaduka commented Oct 9, 2026

Copy link
Copy Markdown
Member

One more follow-up: reactor names in the pill tooltip now load through core-data.

Each pill selects getEntityRecords for the note's reactions only while hovered or focused, so the hand-rolled page walk, its cache, and the summary-identity check are gone. core-data's cache survives remounts (replies remount on every thread select/deselect, which used to drop the names) and only refetches after a comment write. The tooltip shows names only when they match the pill's count; otherwise, it falls back to the count label until the refetch lands.

The query includes post, since core-data requests edit context, which needs it for users without moderate_comments.

Comment on lines +8 to +9
* @package gutenberg
* @since 7.2.0

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
* @package gutenberg
* @since 7.2.0
* @package gutenberg

Reading this header, the class looks like new code introduced in 7.2. In practice, it's a compat layer that overrides core's WP_REST_Comments_Controller so the plugin can support reactions on older WordPress versions.

Because of that, a change needed in just one line of a core method means overriding the whole method here. Therefore, some of the review feedback on this file is about existing core code rather than what this PR introduces.

To make review easier, how about marking with comments where this PR actually changes code inside each method? For example:

	public function get_items_permissions_check( $request ) {
		// START CHANGE: Treat `reaction` like `note`.
		$is_note          = $this->is_note_or_reaction( $request['type'] );
		// END CHANGE.
		$is_edit_context  = 'edit' === $request['context'];

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.

how about marking with comments where this PR actually changes code inside each method?

will do.

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.

Claude made this change, quick note from it:

Added START CHANGE / END CHANGE markers around every line that differs from core (WordPress 7.1.0) and applied the header suggestion in ae52d25.

adamsilverstein and others added 6 commits October 12, 2026 12:25
…on-emojis.ts

Co-authored-by: Aki Hamano <54422211+t-hamano@users.noreply.github.com>
The controller copies whole core methods to change a few lines, which
made it hard for reviewers to tell reaction changes from existing core
code. Wrap every divergence from WordPress 7.1.0 in START CHANGE / END
CHANGE comments, restore core's wording elsewhere in the copies, and
reword the header so the class reads as a compat override.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0126YH7wfjdvbPpuuNv1v92h
WordPress coding standards call for /* */ on comments that span more
than one line.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0126YH7wfjdvbPpuuNv1v92h
Address review feedback: add return and parameter types to the new
helper methods, a full shape for the cached summaries, a minimum of 0
on the summary integers, and drop empty() checks the reaction code does
not need. Inline the constant reaction type and status in the summary
queries so only the note IDs go through prepare().

is_note_or_reaction() keeps an untyped parameter: create requests do
not validate 'type', so a string hint would turn ?type[]= into a fatal.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0126YH7wfjdvbPpuuNv1v92h
The excluded comment types are string literals, so they can go into the
SQL directly instead of through placeholders. Type the hook callbacks to
what core passes them, which also lets the WP_Comment guards go.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0126YH7wfjdvbPpuuNv1v92h

This branch has not been deployed

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

Labels

[Feature] Notes Phase 3 of the Gutenberg roadmap around block commenting [Package] Editor /packages/editor [Status] In Progress Tracking issues with work in progress [Type] Enhancement A suggestion for improvement.

Projects

Status: 🔎 Needs Review

Development

Successfully merging this pull request may close these issues.

Add emoji reactions as a first class comment type