[WC-3556] fix(rich-text): dialog presentation, image paste/drop, list marker formatting - #2407
[WC-3556] fix(rich-text): dialog presentation, image paste/drop, list marker formatting#2407gjulivan wants to merge 6 commits into
Conversation
…of image width and height
23a72a6 to
b28235d
Compare
This comment has been minimized.
This comment has been minimized.
b28235d to
ddbce90
Compare
This comment has been minimized.
This comment has been minimized.
ddbce90 to
ccb2af4
Compare
AI Code Review
What was reviewed
Skipped (out of scope): Findings
|
Pull request type
Description
Groups five related Rich Text fixes plus one File Uploader fix. All changes are
non-breaking; stored content is untouched until the user makes an edit.
Rich Text — dialogs
inline(default, unchanged behaviour) anchors adialog to the toolbar button it was opened from;
focusedcenters it over a dimmedpage and traps the keyboard inside until it closes. Adds the
dialogStyleXMLproperty and a shared
DialogShellcomponent that the image, video, link, help andconfirm dialogs now render through.
container that clips its content (e.g. a pop-up page), used to be cut off with its
Cancel/Insert buttons unreachable. Dialogs now render in a body-level portal, stay
inside the viewport, and scroll internally — the action buttons sit outside the scroll
region so they stay visible.
image dialog's Media Library content inserted the image and closed the dialog without
Insert being pressed.
Rich Text — images
ImagePasteDropextension. Filesthat are too large or are not images are rejected with a reason shown below the editor.
Gated on "Enable default upload", whose description was updated to cover the new paths.
size and rendered at their original dimensions.
Rich Text — list markers
Bullets and numbers now follow the formatting of the list item's first character —
size, bold, italic, colour and font family. Each item is evaluated independently, and
nested lists follow their own first run.
Implementation notes for reviewers: the marker format is derived, never stored.
::markerinherits from its
<li>, but every format the user can apply lands on an inline mark twolevels down, and CSS has no child-to-ancestor selector — so
computeMarkerFormatreadsthe first inline run and publishes the result as
--rt-marker-*custom properties, whichaffect only what
::markerreads and not the item's own content. Two delivery paths areneeded and both call the same pure function:
renderHTML(feedsgetHTML(), copy/paste,initial render) and a
Decoration.nodeplugin (ProseMirror does not re-invoketoDOMwhenonly a node's content changes, so the attribute would otherwise go stale as you type).
No node attribute is declared, so incoming marker data is dropped on parse and recomputed.
The list gutter scales with the marker, since an enlarged marker grows leftward out of
padding-left. The multiplier is marker-length-aware: measured in Chrome, a flat 1.5×clipped three- and four-digit numbers at the maximum font size, so the gutter is derived
from the longest counter's character count (
start + childCount - 1, withlower-romancounted by numeral length rather than digits). With no enlarged marker present the
computed padding is byte-identical to the previous
1.5em.Task lists are out of scope —
taskItemrenders a checkbox withlist-style: noneandhas no
::marker.Opening a page no longer marks the value as changed. Pre-existing and not
list-specific: the editor's value-sync effect called
setContentwith updates enabled,so on every mount the editor's own serialization was written back over any stored value
that was not already byte-identical to
getHTML()— dirtying the bound attribute andfiring the "On change" action without a user edit. Now passes
{ emitUpdate: false };that direction is external value → editor, so echoing back is never wanted. A genuine
edit still emits through
onUpdate.Side effect worth a look: the status bar's "Characters (HTML)" count now reflects the
value as stored rather than the editor's re-serialization (one snapshot moved, 82 → 49).
Arguably the more truthful number, but it will still shift on the user's first real edit.
Rich Text — toolbar
File Uploader
page to submit or a containing dialog to close unexpectedly.
What should be covered while testing?
Rich Text
styleDataFormatmodes (inline and class) for every item below — classmode emits
class+data-*attributes instead of inline styles.dialogs. Check keyboard focus stays inside a Focused dialog and Escape dismisses it.
Insert must stay reachable.
insert or close; only Insert should.
Oversized and non-image files should be rejected with a message. Open content saved in
Rich Text 4 with resized images and confirm sizes are preserved.
the marker follows size, bold, italic, colour and font. Sibling items should format
independently, nested lists should follow their own first run, task list checkboxes
should be untouched, and a long numbered list (100+ items) at a large size should not
clip its numbers.
The "On change" action must not fire and the stored value must be byte-identical.
File Uploader
or the retry button must not submit the form or close the dialog.
Browser note: class-mode marker formatting relies on typed
attr()(
attr(data-marker-font-size px)), which is Chrome 133+ and not yet in Safari or Firefox.This is the same support bar the widget's existing class-mode font size and text colour
already sit on, so it is not a new limitation — but class mode is worth a look in Safari
if that matters for this release. All five
::markerproperties are verified in Chrome.Tests
markerFormat(29),ListItemMarkerFormat(14),ImagePasteDrop,ImageResize,ActionButton,RetryButton,ToolbarConfig, plus the load-time no-write regression inRichText.spec.tsx.pnpm run testinrich-text-web: 403 passing, 26 suites.parameterized marker case per list type in
e2e/RichText.spec.js.CHANGELOG.mdupdated under[Unreleased]in both packages. No version bumps — thosehappen at release time.