Skip to content

Try: Linting notes - #78880

Open
jasmussen wants to merge 2 commits into
trunkfrom
try/linting-notes
Open

jasmussen wants to merge 2 commits into
trunkfrom
try/linting-notes

Conversation

@jasmussen

Copy link
Copy Markdown
Contributor

What?

Starts work for #76996. Note: this PR is heavily Claude-assisted, so will need a good technical review. Or: it can serve as just a proof of concept/test-bed for the feature.

The notes tray is the single surface for everything in the document that needs human attention: notes, suggestions (#73411), and now lint. Like a teacher's notes in the margin of an essay. Always one thread per block. A block can have a human note, a lint message, and (later) a suggestion. They all live in the same thread, as cards inside one shared UI.

GIF showing the feature:

state

Why?

In addition to providing a highly visual interface for lint (notices, warnings, errors), this PR directly addresses feedback around hidden images being hard to find.

How?

From Claude:

  • Canonical item shape. Every annotation conforms to { kind, id, blockClientId, …payload }. NoteThread dispatches on kind. Adding a kind is one case; future 'suggestion' plugs in without touching notes.js.
  • Every kind decides its own source of truth. Notes live in wp_comments via metadata.noteId. Suggestions live in metadata.suggestion. Lint items are derived from rules — the rule's match function is the marker. The unified part is the output shape, not how it was derived.
  • Notes are host-portable. Today the tray rides on the Sidebar API. Long-term it becomes a margin-of-the-document surface. All new code lives in packages/editor/src/components/document-annotations/ with no sidebar-specific imports — moving hosts later is a git mv.
  • Hidden blocks stay mounted (out-of-flow). Annotations need stable coordinates. Hidden+unselected blocks now render with position: absolute; visibility: hidden, preserving WYSIWYG including margin collapsing. Keyboard nav skips them; the lint card is the discovery affordance.

Testing Instructions

Create a new post or page, or open an existing one, just have some hidden blocks. Observe with the block inspector closed, or if you open the Notes archive using the top toolbar button, that there are "Hidden block" lint notes for each hidden block.

Use of AI Tools

Co-authored with Claude Opus 4.7.

@jasmussen jasmussen self-assigned this Jun 2, 2026
@jasmussen jasmussen added [Type] Feature New feature to highlight in changelogs. [Feature] Notes Phase 3 of the Gutenberg roadmap around block commenting labels Jun 2, 2026
@jasmussen
jasmussen requested a review from a team June 2, 2026 12:19
@github-actions github-actions Bot added [Package] Editor /packages/editor [Package] Block editor /packages/block-editor labels Jun 2, 2026
@github-actions

github-actions Bot commented Jun 2, 2026 •

Copy link
Copy Markdown

Size Change: +880 B (+0.01%)

Total Size: 7.74 MB

📦 View Changed
Filename Size Change
build/scripts/block-editor/index.min.js 470 kB +7 B (0%)
build/scripts/editor/index.min.js 532 kB +705 B (+0.13%)
build/styles/block-editor/content-rtl.css 5.68 kB +17 B (+0.3%)
build/styles/block-editor/content-rtl.min.css 4.15 kB +8 B (+0.19%)
build/styles/block-editor/content.css 5.68 kB +18 B (+0.32%)
build/styles/block-editor/content.min.css 4.14 kB +9 B (+0.22%)
build/styles/editor/style-rtl.css 32 kB +30 B (+0.09%)
build/styles/editor/style-rtl.min.css 27.3 kB +29 B (+0.11%)
build/styles/editor/style.css 32 kB +31 B (+0.1%)
build/styles/editor/style.min.css 27.3 kB +26 B (+0.1%)

compressed-size-action

@jameskoster

Copy link
Copy Markdown
Contributor

Should we use Notice here? Especially if the plan is to surface warnings and errors here too.

@jasmussen

Copy link
Copy Markdown
Contributor Author

I see where you're coming from, and it's an option. Conceptually it isn't a fit with the idea of notes being a singular surface for anything related to the document. If we think of a note truly as just an annotation, made by a human, a lint tool, an agent, or a suggestion, then each of those are threads that can be discussions as well. Imagine one user hiding a block, then adding a comment below explaining why they hid that block.

@Mamaduka

Mamaduka commented Jun 9, 2026

Copy link
Copy Markdown
Member

My current reservation is that there's still a lot of work to do on the original Notes feature, and it's not flexible. I would like to avoid introducing complexity if we can for the moment.

@jasmussen
jasmussen marked this pull request as draft June 9, 2026 12:14
@jasmussen

Copy link
Copy Markdown
Contributor Author

Thanks so much for looking. I find that to be a solid reason to revert this one to draft.

The principles embedded in this PR, even if not the code, still feels valid to come back to when we have time!

@jasmussen

Copy link
Copy Markdown
Contributor Author

Noting that I have rebased this branch. I'm keeping it draft state, and I'm still thinking of this as a glorified proof of concept or prototype. Whether the largely AI assisted code can grow into a proper branch and land, I've no opinion of, but I think it is useful still to shepherd this along so that we can test and validate the concept. I still think it works.

The rebase entailed removing a lot of bespoke code from this branch, to rather rely on the larger unification work that has happened to notes overall. It's still 14 files changed, but it should be less code do glance through. With no urgency.

@github-actions

github-actions Bot commented Jul 27, 2026 •

Copy link
Copy Markdown

Flaky tests detected in 18a22b0.
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/32360531148
📝 Reported tests:

Should save the changes in /test/e2e/specs/editor/plugins/wp-editor-meta-box.spec.js, passed after 2 failed attempts.
TimeoutError: page.waitForFunction: Timeout 10000ms exceeded.
    at /home/runner/work/gutenberg/gutenberg/test/e2e/specs/editor/plugins/wp-editor-meta-box.spec.js:34:14
TimeoutError: locator.click: Timeout 10000ms exceeded.
Call log:
  - waiting for locator('role=button[name="Visual"i]')

    at /home/runner/work/gutenberg/gutenberg/test/e2e/specs/editor/plugins/wp-editor-meta-box.spec.js:33:55

@kedarjoyner

kedarjoyner commented Aug 15, 2026 •

Copy link
Copy Markdown

@jasmussen This is really helpful prototype.

Question 1: Is there a way to toggle the floating linting notes?

I appreciate that the hidden-block messages show by default rather than being tucked inside the Notes sidebar. Where I got stuck is turning them off again. I couldn't find a way to get back to a clean view of the page. Once it's known, the user may want to go back to seeing just the design to continue working.

That makes sense for collaboration notes. Someone is waiting on those, and they shouldn't be easy to lose. But I think block status has a different lifecycle:

  • A note persists until someone resolves it. It's addressed to a person.
  • A status — hidden, locked, etc — is learned once. After that may be noise while you're designing, so the ability to toggle these linting notes might be beneficial.

Question 2: Could linting notes work without the Notes feature turned on?

Do you envision a possibility where these two things could be separated in some way even though they share the same space? Notes is people talking to each other. Block status is the editor telling you what's true about a block. I think right now, any site that doesn't enable Notes, would then lose the benefits of these linting notes.

For example, in our multi-site network, Notes are disabled at this time. See another user who requested a filter for this as well, so it's likely there are other groups who do not enable Notes. From a multisite perspective, I can share more about why we decide to disable them if you're interested. I would just need to speak more with our team to gather more details from the DevOps and support perspective. One of the reasons is that they send email notifications, and our team didn't want to risk that going wrong for hundreds of users.

@jasmussen

Copy link
Copy Markdown
Contributor Author

Solid UX questions, nice.

I appreciate that the hidden-block messages show by default rather than being tucked inside the Notes sidebar. Where I got stuck is turning them off again. I couldn't find a way to get back to a clean view of the page. Once it's known, the user may want to go back to seeing just the design to continue working.

There's an ongoing effort relating to Notes in general, for how to show them, which would include this. One of the efforts that @annezazu and I believe @Mamaduka have been working on is a toggle to choose the appearance: full, compact, or possibly entirely hidden (i.e. have to click the Notes toolbar button). There's also a mockup here, which adds a collapse button to the vertical separator between notes and canvas. However part of the concept of these linting notes is to make them extremely obvious first and foremost, and secondly treat them solely as "Notes", ones that the system has authored rather than a user.

You make a good point, however:

That makes sense for collaboration notes. Someone is waiting on those, and they shouldn't be easy to lose. But I think block status has a different lifecycle:

  • A note persists until someone resolves it. It's addressed to a person.
  • A status — hidden, locked, etc — is learned once. After that may be noise while you're designing, so the ability to toggle these linting notes might be beneficial.

Indeed these linting notes would not be dismissible as such, at least not without adjustments to the concept presented here, so this is a good note. That being said, an adjustment would be to simply allow you to turn off linting notes in the canvas, perhaps in the same "compact" menu as the one Anne and George have been looking towards.

Mainly, the motivation for using Notes, aside embracing an existing interface, is that hidden block and probably responsive styles should likely be obvious, always, that's the consistent feedback we've heard across a variety of different issues: people are looking for interfaces that surface these blocks.

Generally the instincts go towards adding more indicators to the List View, which we can, it's just already relatively heavy on UI. Another instinct is a new panel in the document inspector: "Lint"—or a better term, that simply lists out issues. It's not clear any of those are obious enough, however, but I still think we could do both, that they can coexist and complement each other. E.g. both a Lint panel and in-canvas notes; if you end up toggling off the in-canvas notes, you'll still have the panel.

Mostly I'm also just encouraging of PRs that start with minimal solutions: e.g. if it's easier to start with a panel than with in-canvas Notes, let's start there. We might even find it sufficient, in which case this prototype will also have served its purpose. Is that fair?

@kedarjoyner

Copy link
Copy Markdown

There's an ongoing effort relating to Notes in general, for how to show them, which would include this. One of the efforts that @annezazu and I believe @Mamaduka have been working on is a toggle to choose the appearance: full, compact, or possibly entirely hidden (i.e. have to click the Notes toolbar button). There's also a mockup here, which adds a collapse button to the vertical separator between notes and canvas. However part of the concept of these linting notes is to make them extremely obvious first and foremost, and secondly treat them solely as "Notes", ones that the system has authored rather than a user.

I like the direction of the toggle to choose the appearance; that solves the challenge nicely!

However part of the concept of these linting notes is to make them extremely obvious first and foremost, and secondly treat them solely as "Notes", ones that the system has authored rather than a user.

This framing was helpful framing for me: notes the system authors versus the user. Thank you!

Generally the instincts go towards adding more indicators to the List View, which we can, it's just already relatively heavy on UI. Another instinct is a new panel in the document inspector: "Lint"—or a better term, that simply lists out issues. It's not clear any of those are obvious enough, however, but I still think we could do both, that they can coexist and complement each other. E.g. both a Lint panel and in-canvas notes; if you end up toggling off the in-canvas notes, you'll still have the panel.

Mostly I'm also just encouraging of PRs that start with minimal solutions: e.g. if it's easier to start with a panel than with in-canvas Notes, let's start there. We might even find it sufficient, in which case this prototype will also have served its purpose. Is that fair?

Yes! Absolutely. I agree with you that there's room to both, and agree about PRs that start with minimal solutions. I'll continue to follow the Notes discussion! Thinking only of users, and not the nuances with different site setups, it sounds like the Notes solution might solve the need you're hearing from users the best, so that this information is always obvious in the editor rather than hidden from the user behind a tab or separate panel.

I would still advocate for a way to enable Notes with the option to filter out author notes, so that groups like ours could benefit from the system notes too. But I can understand that it might not be feasible for the Notes feature itself. We could put our efforts towards helping shape a complimentary "Lint" tab for groups like ours. I know there must be a better term, but I can't think of one right now :)

@jasmussen

Copy link
Copy Markdown
Contributor Author

Rebased.

jasmussen and others added 2 commits October 22, 2026 10:39
Previously, blocks with `metadata.blockVisibility === false` were
unmounted when unselected. This makes their position unmeasurable,
which the linting interface in the Notes tray needs in order to peg
annotations to their block.

Now those blocks stay mounted with a new `is-block-hidden-unselected`
class. The CSS takes them out of normal flow (`position: absolute;
visibility: hidden; pointer-events: none`) so adjacent visible blocks
lay out exactly as if the hidden block weren't there — preserving
WYSIWYG, including margin collapsing through the gap. `tabIndex: -1`
on hidden+unselected blocks keeps keyboard writing flow skipping them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
All WordPress notes are messages, whether added by hand by selecting
text and commenting, or added for you. So the same mechanism can carry
lint-style findings — "this block is hidden" — alongside them.

This adds the first such rule and surfaces its findings as first-class
threads in the Notes tray, using trunk's notes plumbing rather than
reworking it:

- `useLintItems` derives findings from the block tree, one per rule
  match, tagged `kind: 'lint'`. Nothing is persisted: the tree is the
  source of truth.
- Lint items feed into the same `threads` list that drives the floating
  board, so each card floats aligned to its block just like a note.
- `LintThread` reuses the note thread's canvas chrome (floating card,
  block highlight, keyboard nav, "Back to block"). Findings are derived
  rather than backed by comments, so it is a read-only surface:
  selecting one focuses its block instead of expanding a discussion.
- `calculateNotePositions` falls back to the first measurable thread as
  its anchor, so one unmeasurable block no longer collapses the board.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

🤖 PR meta 🤖

🎉 Props

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: jasmussen <joen@git.wordpress.org>
Co-authored-by: jameskoster <jameskoster@git.wordpress.org>
Co-authored-by: Mamaduka <mamaduka@git.wordpress.org>
Co-authored-by: kedarjoyner <kjoyner@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

Updated as activity occurs, without notifying anyone named here. Add the props-bot label to refresh.

📦 Bundle size

Size Change: +830 B (+0.01%)

Total Size: 9.05 MB

📦 View Changed
Filename Size Change
build/scripts/block-editor/index.min.js 606 kB +7 B (0%)
build/scripts/editor/index.min.js 620 kB +651 B (+0.11%)
build/styles/block-editor/content-rtl.css 6.02 kB +18 B (+0.3%)
build/styles/block-editor/content-rtl.min.css 4.48 kB +8 B (+0.18%)
build/styles/block-editor/content.css 6.02 kB +19 B (+0.32%)
build/styles/block-editor/content.min.css 4.48 kB +8 B (+0.18%)
build/styles/editor/style-rtl.css 30.1 kB +39 B (+0.13%)
build/styles/editor/style-rtl.min.css 25.8 kB +26 B (+0.1%)
build/styles/editor/style.css 30.1 kB +29 B (+0.1%)
build/styles/editor/style.min.css 25.8 kB +25 B (+0.1%)

dcdec4e Run

⚡ Performance

Show the results

Client side metrics exclude the server response time.

front-end-block-theme

Metric b7d7eba trunk % Change
timeToFirstByte 42.65 ms +13.01% -4.45% 42.75 ms +12.98% -2.69% -0.23%
largestContentfulPaint 72 ms +11.11% -2.78% 76 ms +5.26% -5.26% -5.26%
lcpMinusTtfb 28.4 ms +16.9% -7.75% 29.85 ms +8.88% -7.37% -4.86%
wpBeforeTemplate 21.94 ms +13.58% -3.28% 21.98 ms +9.14% -1.41% -0.18%
wpTemplate 16.95 ms +6.31% -6.14% 17.02 ms +3.7% -3.29% -0.41%
wpTotal 39.18 ms +13.45% -4.36% 39.41 ms +12.92% -2.59% -0.58%
wpMemoryUsage 7.66 MB +0% -0% 7.63 MB +0% -0% 0.43%
wpDbQueries 16 +0% -0% 16 +0% -0% 0%

front-end-classic-theme

Metric b7d7eba trunk % Change
timeToFirstByte 34.6 ms +4.91% -0.72% 36.05 ms +7.63% -5.41% -4.02%
largestContentfulPaint 76 ms +5.26% -0% 78 ms +5.13% -2.56% -2.56%
lcpMinusTtfb 41.6 ms +2.76% -1.08% 42.4 ms +3.66% -1.89% -1.89%
wpBeforeTemplate 18.79 ms +5.16% -0.64% 19.07 ms +11.43% -0.79% -1.47%
wpTemplate 12.75 ms +2.98% -1.49% 13.14 ms +6.54% -4.79% -2.97%
wpTotal 31.79 ms +5.44% -0.85% 33.13 ms +8.36% -5.13% -4.04%
wpMemoryUsage 6.35 MB +0% -0% 6.32 MB +0% -0% 0.53%
wpDbQueries 13 +0% -0% 13 +0% -0% 0%

media-processing

Metric b7d7eba trunk % Change
mediaProcessingJpeg 329.39 ms +2.04% -0.57% 328.9 ms +1.7% -0.82% 0.15%
mediaProcessingAvif 4859.68 ms +0.6% -0.5% 4876.24 ms +0.46% -0.33% -0.34%
mediaProcessingJpegToAvif 3399.2 ms +0.89% -0.3% 3384.39 ms +0.53% -0.37% 0.44%

media-upload

Metric b7d7eba trunk % Change
jpegUploadProcessing 1432.1 ms +35.35% -1.67% 1426.9 ms +0.54% -0.4% 0.36%
pngUploadProcessing 211.05 ms +10.61% -2.54% 211.27 ms +2.37% -6.44% -0.1%
largeJpegUploadProcessing 1421.22 ms +1.8% -0.27% 1407.66 ms +0.57% -0.48% 0.96%
multipleImageUploadProcessing 1524.63 ms +8.05% -0.34% 1495.3 ms +2.42% -0.73% 1.96%

post-editor

Metric b7d7eba trunk % Change
serverResponse 342.32 ms +3.59% -9.94% 333.69 ms +2.42% -9.61% 2.59%
firstPaint 242.9 ms +67.72% -21.72% 396.37 ms +2.83% -55.08% -38.72%
domContentLoaded 954.96 ms +2.6% -6.37% 914.1 ms +1.81% -2.4% 4.47%
loaded 955.84 ms +2.64% -6.38% 914.95 ms +1.83% -2.39% 4.47%
firstContentfulPaint 418.72 ms +15% -2.71% 404.71 ms +5.21% -3% 3.46%
firstBlock 2791.96 ms +4.5% -2.21% 2672.16 ms +3.37% -3.2% 4.48%
type 15.66 ms +3.07% -1.92% 15.06 ms +1.66% -1.46% 3.98%
typeWithoutInspector 15.94 ms +5.71% -2.13% 14.71 ms +4.15% -2.04% 8.36%
typeWithTopToolbar 20.49 ms +5.22% -0.59% 19 ms +14.21% -3.11% 7.84%
typeContainer 7.24 ms +4.56% -4.14% 6.73 ms +6.24% -1.49% 7.58%
focus 101.7 ms +7.59% -1.69% 93.01 ms +1.25% -2.59% 9.34%
firstFocus 198.92 ms +0% -0% 179.94 ms +0% -0% 10.55%
selectAll 436.3 ms +0.06% -4.42% 451.26 ms +1.09% -1.26% -3.32%
listViewOpen 61.76 ms +6.78% -4.18% 62.07 ms +6.78% -7.19% -0.5%
inserterOpen 32.83 ms +11.64% -6.64% 30.39 ms +8.23% -2.2% 8.03%
inserterHover 10.13 ms +4.64% -5.73% 9.93 ms +5.44% -7.55% 2.01%
inserterSearch 7.11 ms +6.75% -6.75% 7.37 ms +9.36% -4.34% -3.53%
loadPatterns 506.57 ms +4.36% -3.59% 515.78 ms +10.19% -1.72% -1.79%
wpTotal 333.35 ms +3.23% -10.22% 324.61 ms +2.44% -9.83% 2.69%
wpMemoryUsage 14.70 MB +0% -0% 14.66 MB +0% -0% 0.24%
wpDbQueries 55 +0% -1.82% 55 +0% -0% 0%

site-editor

Metric b7d7eba trunk % Change
serverResponse 277.4 ms +2.93% -7.32% 269.81 ms +2.95% -8.57% 2.81%
firstPaint 223.92 ms +8.99% -5.69% 205.88 ms +32.19% -17.26% 8.76%
domContentLoaded 869.68 ms +1.54% -2.73% 797.67 ms +3.91% -3.12% 9.03%
loaded 870.68 ms +1.57% -2.71% 798.67 ms +3.89% -3.12% 9.02%
firstContentfulPaint 381.27 ms +3.16% -2.53% 350.15 ms +2.75% -2.75% 8.89%
firstBlock 3131.24 ms +0.99% -1.73% 2898.03 ms +1.57% -1.02% 8.05%
type 15.37 ms +1.76% -4.1% 14.32 ms +0.49% -5.1% 7.33%
navigate 95.21 ms +12.66% -7.72% 93.22 ms +9.73% -23.7% 2.13%
loadPatterns 1004.77 ms +13.63% -11.81% 888.63 ms +15.5% -5.85% 13.07%
loadPages 943.78 ms +4.03% -3.8% 965.97 ms +5.84% -3.3% -2.3%
wpTotal 270.55 ms +3.06% -7.6% 263.15 ms +2.95% -8.82% 2.81%
wpMemoryUsage 12.71 MB +0% -0% 12.68 MB +0% -0% 0.27%
wpDbQueries 44.5 +1.12% -1.12% 44.5 +1.12% -1.12% 0%

dcdec4e Run

🏁 Flaky tests

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.

Regression: updating a specific option will only change its value and will not corrupt others in /test/e2e/specs/editor/various/core-settings.spec.js, passed after 1 failed attempt.
Error: expect(received).toStrictEqual(expected) // deep equality

- Expected  - 1
+ Received  + 1

  Array [
    "rewrite_rules",
-   "SERIALIZED DATA",
+   "",
  ]
    at forEach (/home/runner/work/gutenberg/gutenberg/test/e2e/specs/editor/various/core-settings.spec.js:46:26)
    at /home/runner/work/gutenberg/gutenberg/test/e2e/specs/editor/various/core-settings.spec.js:43:35
keeps the blocks selected after dropping a multi-selection in /test/e2e/specs/editor/various/draggable-blocks.spec.js, passed after 1 failed attempt.
TypeError: Cannot read properties of null (reading 'y')
    at /home/runner/work/gutenberg/gutenberg/test/e2e/specs/editor/various/draggable-blocks.spec.js:824:57
    at dragSelectionBelowLanding (/home/runner/work/gutenberg/gutenberg/test/e2e/specs/editor/various/draggable-blocks.spec.js:823:3)
    at /home/runner/work/gutenberg/gutenberg/test/e2e/specs/editor/various/draggable-blocks.spec.js:908:3
refuses the drop and uploads nothing in /test/e2e/specs/editor/various/single-file-placeholder-drop.spec.js, passed after 1 failed attempt.
Error: expect(received).toHaveLength(expected)

Expected length: 0
Received length: 1
Received array:  [{"_links": {"about": [{"href": "http://localhost:8889/wp-json/wp/v2/types/attachment"}], "author": [{"embeddable": true, "href": "http://localhost:8889/wp-json/wp/v2/users/1"}], "collection": [{"href": "http://localhost:8889/wp-json/wp/v2/media"}], "curies": [{"href": "https://api.w.org/{rel}", "name": "wp", "templated": true}], "replies": [{"embeddable": true, "href": "http://localhost:8889/wp-json/wp/v2/comments?post=223"}], "self": [{"href": "http://localhost:8889/wp-json/wp/v2/media/223", "targetHints": {"allow": ["GET", "POST", "PUT", "PATCH", "DELETE"]}}], "wp:attached-to": [{"embeddable": true, "href": "http://localhost:8889/wp-json/wp/v2/posts/222", "id": 222, "post_type": "post"}]}, "alt_text": "", "author": 1, "caption": {"rendered": ""}, "class_list": ["post-223", "attachment", "type-attachment", "status-inherit", "hentry", "entry"], "comment_status": "open", "date": "2026-10-22T09:14:01", "date_gmt": "2026-10-22T09:14:01", "description": {"rendered": "<p class=\"attachment\"><a href='http://localhost:8889/wp-content/uploads/2026/10/aea6734a-26f7-4fb8-8e87-af05401f05f0.png'><img loading=\"lazy\" decoding=\"async\" width=\"10\" height=\"10\" src=\"http://localhost:8889/wp-content/uploads/2026/10/aea6734a-26f7-4fb8-8e87-af05401f05f0.png\" class=\"attachment-medium size-medium\" alt=\"\" style=\"width:100%;height:100%;max-width:10px;\" /></a></p>
"}, "featured_media": 0, "filename": "aea6734a-26f7-4fb8-8e87-af05401f05f0.png", "filesize": 80, "guid": {"rendered": "http://localhost:8889/wp-content/uploads/2026/10/aea6734a-26f7-4fb8-8e87-af05401f05f0.png"}, "id": 223, "link": "http://localhost:8889/?attachment_id=223", "media_details": {"file": "2026/10/aea6734a-26f7-4fb8-8e87-af05401f05f0.png", "filesize": 80, "height": 10, "image_meta": {"alt": "", "aperture": "0", "camera": "", "caption": "", "copyright": "", "created_timestamp": "0", "credit": "", "focal_length": "0", "iso": "0", "keywords": [], "orientation": "0", "shutter_speed": "0", "title": ""}, "sizes": {}, "width": 10}, "media_type": "image", "meta": [], "mime_type": "image/png", "modified": "2026-10-22T09:14:01", "modified_gmt": "2026-10-22T09:14:01", "ping_status": "closed", "post": 222, "slug": "aea6734a-26f7-4fb8-8e87-af05401f05f0", "source_url": "http://localhost:8889/wp-content/uploads/2026/10/aea6734a-26f7-4fb8-8e87-af05401f05f0.png", "status": "inherit", "template": "", "title": {"rendered": "aea6734a-26f7-4fb8-8e87-af05401f05f0"}, "type": "attachment"}]
    at /home/runner/work/gutenberg/gutenberg/test/e2e/specs/editor/various/single-file-placeholder-drop.spec.js:71:45
three users concurrently edit a large post with diverse blocks in /test/e2e/specs/editor/collaboration/collaboration-stress.spec.ts, passed after 1 failed attempt.
TimeoutError: locator.waitFor: Timeout 17500ms exceeded.
Call log:
  - waiting for getByRole('button', { name: /Collaborators list/ }) to be visible

    at map (/home/runner/work/gutenberg/gutenberg/test/e2e/specs/editor/collaboration/fixtures/collaboration-utils.ts:193:7)
    at CollaborationUtils.waitForMutualDiscovery (/home/runner/work/gutenberg/gutenberg/test/e2e/specs/editor/collaboration/fixtures/collaboration-utils.ts:188:10)
    at /home/runner/work/gutenberg/gutenberg/test/e2e/specs/editor/collaboration/collaboration-stress.spec.ts:416:28

dcdec4e Run

@jasmussen

Copy link
Copy Markdown
Contributor Author

Rebased on current trunk. This is the state, still just showing a lint note for a fully hidden block:

state

This message is for the Notes maintainers already subscribed, not necesarily to respond to urgently—I know we're busy with 7.2 beta. But I still think the concept of this branch is valid: notes are messages however they got added, and a hidden block is worth knowing about just like a suggestion or comment from a user. So let me know when we ready to look at this as something we can potentiallymerge.

In maintaining this branch, it still doesn't fork any of the notes plumbing: lint findings are just entries in the same threads list Notes already renders, floating off the same board, so each card tracks its block exactly like a note does.

As part of the rebase, block-editor no longer unmounts hidden blocks when they're deselected, since otherwise there's no rect to anchor to, and calculateNotePositions now falls back to the first measurable thread as its anchor, which added the nice little nimation. One caveat I'd want your eyes on: useLintItems derives findings from the block tree on every store change, which re-renders Notes — that cuts against the board's don't-re-render-on-canvas-changes principle, and I'd rather fix it the way you'd want it fixed than guess.

@jasmussen
jasmussen marked this pull request as ready for review October 22, 2026 09:04

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] Block editor /packages/block-editor [Package] Editor /packages/editor [Type] Feature New feature to highlight in changelogs.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants