Skip to content

Rich Text: Move RichTextShortcut and RichTextInputEvent into @wordpress/rich-text#79828

Merged
adamsilverstein merged 6 commits into
trunkfrom
extract/rich-text-shortcut-input-event
Jul 7, 2026
Merged

Rich Text: Move RichTextShortcut and RichTextInputEvent into @wordpress/rich-text#79828
adamsilverstein merged 6 commits into
trunkfrom
extract/rich-text-shortcut-input-event

Conversation

@adamsilverstein

Copy link
Copy Markdown
Member

What?

Moves RichTextShortcut, RichTextInputEvent, and their shared contexts (keyboardShortcutContext, inputEventContext) from @wordpress/block-editor into @wordpress/rich-text, exposed via the rich-text private APIs. The block-editor files become thin back-compat re-exports.

Extracted from #78471 per @ntsekouras's review suggestion so it can land first as a smaller, self-contained refactor.

Why?

These format helper components have no block-editor specific logic: they only register callbacks into a context that the rich text field owner provides and dispatches. @wordpress/rich-text is their natural home, and housing them there lets any rich text field (not just the block-editor canvas RichText) provide the contexts. #78471 (RichTextControl, the standalone rich text form control) is the first consumer outside the block editor.

How?

  • New in @wordpress/rich-text (private APIs):
    • src/contexts.js - keyboardShortcutContext and inputEventContext, previously created in block-editor's rich-text/index.js.
    • src/keyboard-shortcut.js / src/input-event.js - RichTextShortcut and RichTextInputEvent, moved as-is except the "latest callback" ref is now updated inside an effect rather than during render, which also resolves the two react-hooks/refs eslint suppressions the old files needed.
  • @wordpress/block-editor: rich-text/shortcut.js and rich-text/input-event.js re-export the moved components from the rich-text private APIs, keeping the existing public import paths working (@wordpress/format-library and third-party formats import them from @wordpress/block-editor); rich-text/index.js and the block-fields RichTextControl read the contexts from the rich-text private APIs.

No behavior change. Everything stays private/internal: the components were only ever public via the block-editor re-export, which is unchanged.

Testing instructions

  1. npm run wp-env start && npm start.
  2. In the post editor, confirm format keyboard shortcuts still work in a paragraph: ⌘B / ⌘I / ⌘K, and ⌃⌥X for inline code (these go through RichTextShortcut).
  3. Confirm the strikethrough format's formatStrikethrough input event and list-outdent behavior still work (e.g. delete at the start of an indented list item), which exercise RichTextInputEvent.
  4. npm run test:unit -- packages/rich-text packages/block-editor/src/components/rich-text - 218 tests pass.

Types of changes

Code quality / refactor (non-breaking, no behavior change).

…ss/rich-text

These format helper components and their contexts have no block-editor
specific logic, so house them in the rich-text package where any rich
text field owner (not just the block-editor canvas) can provide the
contexts. The block-editor files re-export them from the rich-text
private APIs for back-compat, since format-library and third-party
formats import them from @wordpress/block-editor.

The move also fixes the react-hooks/refs suppression in both
components by keeping the latest callback in a ref updated inside an
effect instead of during render.

Extracted from #78471 per review feedback.
@adamsilverstein adamsilverstein requested a review from ellatrix as a code owner July 2, 2026 16:36
@adamsilverstein adamsilverstein added [Type] Code Quality Issues or PRs that relate to code quality [Package] Rich text /packages/rich-text labels Jul 2, 2026
@adamsilverstein adamsilverstein added [Type] Code Quality Issues or PRs that relate to code quality [Package] Rich text /packages/rich-text labels Jul 2, 2026
@github-actions github-actions Bot added the [Package] Block editor /packages/block-editor label Jul 2, 2026
@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown

Size Change: +172 B (0%)

Total Size: 7.67 MB

📦 View Changed
Filename Size Change
build/scripts/block-editor/index.min.js 417 kB -107 B (-0.03%)
build/scripts/rich-text/index.min.js 14.4 kB +279 B (+1.97%)

compressed-size-action

@andrewserong andrewserong left a comment

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.

This looks like a good move to me (and sets up re-use nicely for the larger rich text control PR).

Smoke tests appropriately in the editor via bold, italic, inline code shortcuts.

LGTM!

@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown

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 props-bot label.

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: adamsilverstein <adamsilverstein@git.wordpress.org>
Co-authored-by: andrewserong <andrewserong@git.wordpress.org>
Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org>
Co-authored-by: Mamaduka <mamaduka@git.wordpress.org>

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

@ntsekouras ntsekouras left a comment

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.

Looks good, thanks! I've left a small comment.

I still think that we could also move the listeners (as mentioned here), but we can still consider it afterwards.

Comment thread packages/rich-text/src/input-event.js Outdated
adamsilverstein and others added 3 commits July 6, 2026 12:41
Replace the useRef + passive useEffect pattern with useEvent from
@wordpress/compose, which syncs via useInsertionEffect and guards
against reading stale data. Addresses review feedback.
@Mamaduka

Mamaduka commented Jul 7, 2026

Copy link
Copy Markdown
Member

The new RichTextInputEvent and RichTextShortcut can be just hooks and old, unstable components, thin wrappers. I think I remember seeing an old note from @ellatrix about this in the codebase.

Another Nit: Let's use React's component naming convention (PascalCase) for context as well; it's recommended.

// `keyboardShortcutContext` with standalone rich text fields. Re-exported here
// for back-compat (e.g. `@wordpress/format-library` imports it from
// `@wordpress/block-editor`).
export const { RichTextShortcut } = unlock( richTextPrivateApis );

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.

Do we need these two files? I think we can export directly from index.js, no?

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.

Fixed in 15b546f - the two files are gone, both components are now exported directly from the rich text index.

@ntsekouras

ntsekouras commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

The new RichTextInputEvent and RichTextShortcut can be just hooks

+1 to that.

What I had in mind by saying move the listeners was to actually absorb more of the glue needed for consumers.

I prototyped with Claude Fable 5 something along the lines of what I had in mind. Noting I haven't reviewed that in depth though..

In the above changeset rich-text now owns the callback registries and dispatches them from useRichText's own listener pipeline, consumers render a single RichTextEventsProvider with the events object useRichText returns, and the block-editor components become thin back-compat wrappers around the new hooks (@Mamaduka's suggestion).

--cc @ellatrix

React contexts are components, so follow the component naming
convention as suggested in review.
The two standalone files only re-exported the components from
@wordpress/rich-text private APIs; export them directly from the rich
text index instead, as suggested in review.
adamsilverstein added a commit that referenced this pull request Jul 7, 2026
Brings over the review changes from the extraction PR and applies the
same rename to the consolidated-branch consumers.
@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown

Flaky tests detected in 15b546f.
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/28887952369
📝 Reported issues:

@Mamaduka Mamaduka 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.

I think we can merge this to allow faster iteration/reviews on #78471.

The new private APIs can be changed in follow-ups.

@adamsilverstein adamsilverstein merged commit 35812c3 into trunk Jul 7, 2026
44 of 45 checks passed
@adamsilverstein adamsilverstein deleted the extract/rich-text-shortcut-input-event branch July 7, 2026 22:03
@github-actions github-actions Bot added this to the Gutenberg 23.6 milestone Jul 7, 2026
@ellatrix

ellatrix commented Jul 7, 2026

Copy link
Copy Markdown
Member

Tbh, I wish we could get rid of RichTextInputEvent and RichTextShortcut and move it outside React the format object.

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

Labels

[Package] Block editor /packages/block-editor [Package] Rich text /packages/rich-text [Type] Code Quality Issues or PRs that relate to code quality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants