Skip to content

Write editor: image properties panel with alignment#49536

Open
allilevine wants to merge 5 commits into
trunkfrom
fix/write-image-align-modal
Open

Write editor: image properties panel with alignment#49536
allilevine wants to merge 5 commits into
trunkfrom
fix/write-image-align-modal

Conversation

@allilevine

@allilevine allilevine commented Jun 10, 2026

Copy link
Copy Markdown
Member

Fixes RSM-3979 and RSM-3982.

Proposed changes

  • Add an Edit pencil on every image in the Write editor that opens a new image properties panel — alt text, size, alignment, set-as-featured all in one surface. Replaces the inline ALT and Size buttons.
  • Add left / center / right alignment for images. Center is now explicit (align:"center" + aligncenter class) so the published view centers reliably across themes.
  • The panel is non-modal: it docks to the bottom-right on desktop and slides up as a full-width bottom sheet on mobile. Changes apply live so the rest of the editor stays visible and editable.
  • When the panel is open, the active figure gets a focus outline so multi-image switching is clear.
  • Fix the indicator-state bug where the top-toolbar Left button stayed highlighted whenever a text block had no explicit alignment (i.e. always, by default). Now only highlights when alignment is explicitly set.
  • As a side effect of going from 4 inline buttons to 3 (×, Caption, Edit) and anchoring the new wrapper to the image bounds, the Thumbnail and Medium overflow from RSM-3980 is also addressed.
Screenshot 2026-06-10 at 1 57 07 PM

Related product discussion/links

  • Linear: RSM-3979, RSM-3982
  • Builds on #48980 (size presets), which had decided alignment was an open question

Does this pull request change what data or activity we track or use?

No. The image block's align attribute is added to the round-trip allowlist; no new tracking events.

Testing instructions

Setup: Open any post (new or existing) in the Write editor with at least one image inserted from the media library.

Edit panel:

  • Hover an image — the floating bar should show ×, Caption, ✎ (Edit pencil). Click the Edit pencil.
  • Panel docks to bottom-right (or slides up from bottom on mobile). Alt text, Size (Thumbnail/Medium/Large/Full), Alignment (Left/Center/Right), and Set-as-featured controls are all there.
  • Change the alignment and watch the image update live behind the panel. Try Medium + Left to see text wrap around it.
  • Click Done, ×, or press Escape to close — focus returns to the Edit pencil.
  • While the panel is open, you should still be able to type in the editor, click other paragraphs, and use Cmd/Ctrl+S to save.

Multi-image:

  • Insert two images. Open the panel on image 1 — should see a blue outline around it. Click image 2's Edit pencil — outline jumps to image 2, panel updates.

Insert-while-editing:

  • With the panel open, click the toolbar Image icon or type /image. The panel should close and the insert modal should open. The previous edit's changes are committed as a single undo entry.

Round-trip with block editor:

  • Set Left or Right alignment, save the post, open it in the block editor — alignment should be preserved (align:"left" etc in the block markup).
  • Conversely, open a block-editor post with a center-aligned image in Write — Center should be pre-selected in the panel.

Indicator bug (RSM-3982):

  • Open any post with no aligned text. Look at the top-toolbar Left alignment button — it should NOT appear highlighted. Click into different paragraphs; still not highlighted. (Before this PR, it was always highlighted.)

Mobile:

  • In Chrome devtools, switch to a phone viewport (e.g. iPhone 14, 390×844). Open the Edit pencil — panel should slide up from the bottom edge as a full-width bottom sheet. The figure should scroll into view above the sheet.

Accessibility:

  • Tab into the panel — focus moves through Alt, the radio groups, featured checkbox, Done. Tab again exits the panel into the document (no focus trap; intentional for non-modal dialogs).
  • Press Escape from any focus position (panel, editor, title) — panel closes and focus returns to the Edit pencil.
  • role="dialog" and aria-modal="false" are set on the panel; aria-labelledby points to the panel title.

Known mobile caveat: when the Alt text input is focused on iOS, the software keyboard may cover the lower portion of the bottom sheet. Tracked as polish for follow-up.

🤖 Generated with Claude Code

@github-actions

Copy link
Copy Markdown
Contributor

Thank you for your PR!

When contributing to Jetpack, we have a few suggestions that can help us test and review your patch:

  • ✅ Include a description of your PR changes.
  • 🔴 Add a "[Status]" label (In Progress, Needs Review, ...).
  • ✅ Add testing instructions.
  • ✅ Specify whether this PR includes any changes to data or privacy.
  • ✅ Add changelog entries to affected projects

This comment will be updated as you work on your PR and make changes. If you think that some of those checks are not needed for your PR, please explain why you think so. Thanks for cooperation 🤖


Follow this PR Review Process:

  1. Ensure all required checks appearing at the bottom of this PR are passing.
  2. Make sure to test your changes on all platforms that it applies to. You're responsible for the quality of the code you ship.
  3. You can use GitHub's Reviewers functionality to request a review.
  4. When it's reviewed and merged, you will be pinged in Slack to deploy the changes to WordPress.com simple once the build is done.

If you have questions about anything, reach out in #jetpack-developers for guidance!

@github-actions github-actions Bot added the [Status] Needs Author Reply We need more details from you. This label will be auto-added until the PR meets all requirements. label Jun 10, 2026
@github-actions

github-actions Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Are you an Automattician? Please test your changes on all WordPress.com environments to help mitigate accidental explosions.

  • To test on WoA, go to the Plugins menu on a WoA dev site. Click on the "Upload" button and follow the upgrade flow to be able to upload, install, and activate the Jetpack Beta plugin. Once the plugin is active, go to Jetpack > Jetpack Beta, select your plugin (WordPress.com Site Helper), and enable the fix/write-image-align-modal branch.
  • To test on Simple, run the following command on your sandbox:
bin/jetpack-downloader test jetpack-mu-wpcom-plugin fix/write-image-align-modal

Interested in more tips and information?

  • In your local development environment, use the jetpack rsync command to sync your changes to a WoA dev blog.
  • Read more about our development workflow here: PCYsg-eg0-p2
  • Figure out when your changes will be shipped to customers here: PCYsg-eg5-p2

@jp-launch-control

jp-launch-control Bot commented Jun 10, 2026

Copy link
Copy Markdown

Code Coverage Summary

Coverage changed in 2 files.

File Coverage Δ% Δ Uncovered
projects/packages/jetpack-mu-wpcom/src/features/write/view.js 0/5888 (0.00%) 0.00% 187 💔
projects/packages/jetpack-mu-wpcom/src/features/write/write.php 487/618 (78.80%) 1.52% -6 💚

Full summary · PHP report · JS report

Coverage check overridden by I don't care about code coverage for this PR Use this label to ignore the check for insufficient code coveage. .

@allilevine allilevine requested a review from kbrown9 June 10, 2026 18:04
@kbrown9

kbrown9 commented Jun 10, 2026

Copy link
Copy Markdown
Member

I ran into an edge case where I couldn't get the hover to work properly:

  1. Insert an image and align it left (I think this also occurs if you align right).
  2. Insert another image below the first one.
  3. Notice that the hover target for the first image is not correct.

I haven't had a chance to dig into the cause yet.

@kbrown9

kbrown9 commented Jun 10, 2026

Copy link
Copy Markdown
Member

A few other things I noticed:

  • The full size selection for images in the block editor is not compatible with Write, despite the fact that Write has a full selection as well.
  • The full selection in the Write editor doesn't set the full selection in the block editor.
  • The wide selection in the block editor is not compatible with Write, which I think is fine because Write doesn't have a wide selection.

For the full selection, I suspect that the block and write editors set different classes. We probably want Write to set the same classes as the block editor.

@allilevine

Copy link
Copy Markdown
Member Author

I ran into an edge case where I couldn't get the hover to work properly:

@kbrown9 Thanks! This should be fixed in 6dfae15 and images should no longer overlap like that.

The full size selection for images in the block editor is not compatible with Write, despite the fact that Write has a full selection as well.
The full selection in the Write editor doesn't set the full selection in the block editor.

You're right, it looks like the block editor sets image size in different ways. I've added more checks to make sure we get it in both directions.

Adds left / center / right image alignment plus an image properties panel
(alt text, size, alignment, featured image) opened by a single Edit pencil
on each image. Replaces the inline ALT and Size buttons.

The panel is non-modal: it docks to the bottom-right of the viewport on
desktop and slides up as a full-width bottom sheet on mobile, so changes
apply live to the figure while the rest of the editor remains visible
and editable. Multi-image switching is signaled with an outline on the
active figure.

Also fixes the indicator-state bug where the top-toolbar Left button
showed as active whenever text-block alignment was the empty default —
now it only highlights when alignment is explicitly set.

Round-trip with the block editor: images are serialized with explicit
align attribute + align{left,center,right} class, matching what the
block editor emits.

Fixes RSM-3979 and RSM-3982.
Two follow-ups from review:

- A floated figure (alignleft/alignright) bled into the next figure's
  bounding box because the next figure didn't clear the float.  Hover
  detection picked the wrong figure (whichever was later in the DOM
  won the z-order even when visually it was the earlier image being
  pointed at).  Fixed with `clear: both` on `.bw-content figure`:
  floated figures now stack vertically in the editor while text
  paragraphs still wrap around the float.  The published view is
  unaffected.

- Block-editor inserts often omit the `sizeSlug` attribute even when
  the img src already matches a registered size (e.g. Large is the
  default media URL).  In that case the figure had no `size-X` class,
  so the Edit panel's size radio group showed nothing selected even
  though the image was rendering at a recognisable preset size.  Open
  now resolves the slug from the img URL via the media library's
  registered sizes and stamps the matching class onto the figure, so
  the panel reflects what the user sees and saves are explicit.
@allilevine allilevine force-pushed the fix/write-image-align-modal branch from 6dfae15 to 13b1812 Compare June 12, 2026 14:26
The Size and Alignment radiogroups in the image edit panel used
role="radio" without the keyboard pattern that role implies — every
option was an individual tab stop and arrow keys did nothing.

Add roving tabindex (only the active option has tabindex=0; others -1)
and arrow / Home / End key handling on each radiogroup.  Arrow keys
move focus AND activate the new option, matching the WAI-ARIA radio
authoring pattern; Tab exits the group cleanly to the next focusable
control instead of stepping through every option.

State sync happens via the existing syncEditImageModalRadios callback
so aria-checked and tabindex stay in lockstep with state.editingImageAlign
and state.editingImageSize on every change.
@allilevine allilevine added the I don't care about code coverage for this PR Use this label to ignore the check for insufficient code coveage. label Jun 12, 2026
@allilevine

allilevine commented Jun 12, 2026

Copy link
Copy Markdown
Member Author

The Code Coverage Requirement bot is flagging the 174 new lines in view.js. Worth noting that the whole file is at 0/5875 (0%) baseline — this PR doesn't introduce a new untestable pattern, it just adds to an existing one. The Write editor's view.js is an Interactivity API entry point with side effects on import; meaningfully testing it needs jsdom plus a refactor to extract pure helpers (matching the undo-history.js precedent).

Filing as a follow-up rather than carving off a handful of helpers in this PR — the coverage gap is a property of the whole module, not these specific changes, and cleaning it up is its own focused effort. Tracked as RSM-4353.

The image block serializer was stripping the width and height attrs
from the <img> element, so the saved markup looked like:

  <img src="..." alt="" class="wp-image-X"/>

Without intrinsic dimensions, themes that only ship the default
`img { max-width: 100%; height: auto }` rule let the image stretch
to fill its container — even when the URL points at a resized 150x150
file, the published post would render it at full content width.
This was visible at Thumbnail and Medium sizes on themes that don't
explicitly style `figure.size-thumbnail`.

applyMediaSizeToFigure already sets `width` / `height` attrs on the
DOM img every time the user picks a size; the bug was the serializer
not propagating them.  Now emits:

  <img src="..." alt="" class="wp-image-X" width="150" height="150"/>

Matching the block editor's output.

Copilot AI 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.

Pull request overview

This PR enhances the Write editor’s image UX by replacing inline per-image ALT/Size controls with a consolidated, non-modal image properties panel (alt text, size, alignment, featured image), and by ensuring image alignment (including explicit centering) round-trips reliably through block markup.

Changes:

  • Add a per-image Edit (pencil) control that opens a docked/bottom-sheet image properties panel; apply edits live and coalesce undo on close.
  • Add left/center/right image alignment support and serialize explicit align + align* classes for consistent theme rendering.
  • Fix the toolbar alignment indicator so it only highlights when alignment is explicitly set (not on default alignment).

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
projects/packages/jetpack-mu-wpcom/tests/php/features/write/Write_Test.php Updates PHPUnit coverage to assert image align is supported and included in the allowlist sync checks.
projects/packages/jetpack-mu-wpcom/src/features/write/write.php Adds align to the allowed image attrs and introduces new interactivity state for edit-mode/panel behavior.
projects/packages/jetpack-mu-wpcom/src/features/write/view.js Implements edit-panel state management, alignment + size handling, updated serialization, and fixes default toolbar alignment highlighting.
projects/packages/jetpack-mu-wpcom/src/features/write/style.css Adds alignment styling, updates figure controls positioning, and styles the new non-modal edit panel + active-figure outline.
projects/packages/jetpack-mu-wpcom/changelog/fix-write-image-align-modal Changelog entry for the new image properties panel and alignment support.

Comment thread projects/packages/jetpack-mu-wpcom/src/features/write/write.php Outdated
Comment thread projects/packages/jetpack-mu-wpcom/src/features/write/view.js Outdated
Comment thread projects/packages/jetpack-mu-wpcom/src/features/write/view.js Outdated
Three stale comments referred to the original "center alignment emits
no class / no attribute" behavior from an earlier iteration of this
PR.  Center is now always made explicit on save (aligncenter class +
align:"center" in block JSON) so themes center reliably, and the
allowlist accepts the attribute but the value check rejects wide/full.

Comments updated to match — no behavior change.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

I don't care about code coverage for this PR Use this label to ignore the check for insufficient code coveage. [mu wpcom Feature] Write [Package] Jetpack mu wpcom WordPress.com Features [Status] Needs Author Reply We need more details from you. This label will be auto-added until the PR meets all requirements. [Tests] Includes Tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants