Writing Flow: Fix format toolbar not appearing when selecting text from block edge#77136
Writing Flow: Fix format toolbar not appearing when selecting text from block edge#77136
Conversation
When using the Top Toolbar setting, highlighting text starting from the left edge of a paragraph (on the block wrapper padding) did not show Bold/Italic formatting options. This happened because the RichText element never received focus when the drag started outside its contentEditable boundary, so its selection handlers never fired and the store was missing the attributeKey needed for isSelected. Update useSelectionObserver to detect non-collapsed selections within a RichText element that doesn't have focus, and dispatch a full selectionChange with the proper attributeKey and offsets. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…edge Verifies that Bold and other formatting options appear in the Top Toolbar when the user starts a text selection from just outside the contentEditable boundary (the block wrapper padding) and drags into the paragraph text. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2edd798 to
54f148e
Compare
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message. To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
|
Size Change: +180 B (0%) Total Size: 7.74 MB 📦 View Changed
ℹ️ View Unchanged
|
|
Flaky tests detected in a2f93a1. 🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/24137658081
|
Mamaduka
left a comment
There was a problem hiding this comment.
Could be a regression after refactoring in #47525.
- All these nested conditions are becoming hard to follow; maybe we could simplify them if possible.
- The fix resembles logic in the next block-scope. Do we need a reusable abstraction?
Possibly. Any specific paths in mind?
Maybe, although I think it's not exactly the same use case, and the abstraction would likely make things even less readable and more complex. |
Nothing specific, just something that stood out when scanning the code.
Maybe @ellatrix has suggestions. |
Happy to address any specific suggestions there, although at this point, this feels more like a minor code quality improvement and not a blocker for the PR. Let me know. |
Mamaduka
left a comment
There was a problem hiding this comment.
Can confirm that this fixes the issue. The minor code quality improvements can be done separately or as needed.
| const richTextElement = | ||
| ! selection.isCollapsed && | ||
| ( getRichTextElement( startNode ) || | ||
| getRichTextElement( endNode ) ); |
There was a problem hiding this comment.
Nit (non-blocking): A ternary might be more suitable here - isCollapsed ? null : richTextElement.
There was a problem hiding this comment.
From what I understand, you're suggesting:
const richTextElement2 = selection.isCollapsed ? null : ( getRichTextElement( startNode ) || getRichTextElement( endNode ) );and to me it's very similar to what we already have:
const richTextElement = ! selection.isCollapsed && ( getRichTextElement( startNode ) || getRichTextElement( endNode ) );so I think I'll just go with what's there already.
| // within a RichText that doesn't have focus | ||
| // (e.g. the user started dragging from the block | ||
| // wrapper padding), dispatch a full | ||
| // selectionChange so the format toolbar appears. |
There was a problem hiding this comment.
Should we also transfer focus in this case?
There was a problem hiding this comment.
We could, but to be fair, it's not the goal of the PR.
Currently (before and after the PR) after any selection of text inside a block, we'll keep the editor canvas as the focused element.
Which element would you choose to focus in this case, and in the other case? Happy to follow up in another PR if we agree this makes sense.
There was a problem hiding this comment.
Of course, this comment wasn't blocking for this PR. Maybe the selection start? 🤔 Although maybe we don't need to?
The thing that triggered this question was that I selected text from block edge and tried to type after that and also tried to cut with keyboard, but this might not have to do with transferring the focus (at least for keyboard cut)..
There was a problem hiding this comment.
Maybe the selection start?
What if we start the selection from the right padding instead of the left one? Then it would have to be the selection end 😉
Maybe we're overcomplicating things, and we should keep the focus as-is.
What?
This PR fixes format toolbar not appearing when selecting text from either of the block edges.
Why?
Highlighting text starting from the left edge of a paragraph (on the block wrapper padding) did not show the formatting options in the top toolbar. This happened because the
RichTextelement never received focus when the drag started outside itscontentEditableboundary, so its selection handlers never fired.Fixes #77133.
How?
This PR updates
useSelectionObserverto detect non-collapsed selections within an unfocusedRichTextand dispatch a fullselectionChange.Testing Instructions
Testing Instructions for Keyboard
Same
Screenshots or screencast
Before:
Screen.Recording.2026-04-08.at.12.22.36.mov
After:
Screen.Recording.2026-04-08.at.12.38.56.mov
Use of AI Tools
I used Claude Code with Opus 4.6 and verified the changes manually.