Commit c043b2aab3e for woocommerce

commit c043b2aab3e851e9998330dba014064ad2e58f43
Author: Allison Levine <1689238+allilevine@users.noreply.github.com>
Date:   Tue Sep 8 09:07:23 2026 -0400

    fix(email-editor): stop Media & Text floating so buttons don't bleed over it (#68443)

    * fix(email-editor): stop Media & Text floating so buttons don't bleed over it

    The Media & Text wrapper table emitted align="left" (from the default text
    align), which email clients render as float:left. That pulled the block out of
    normal flow, so the block after it failed to clear it — a following buttons
    block overlapped it and painted its background across the media and text above.

    Drop the align attribute; horizontal alignment is already carried by the
    text-align declaration in the wrapper's inline styles, so alignment is preserved
    while the block stays in normal flow. This is the same fix #66833 applied to the
    gallery wrapper for the same reason.

    Verified by rendering a media-text block followed by a center-justified buttons
    block through the real renderer and loading the output in WebKit at 390px: the
    button background covers the whole media & text block before the change and sits
    cleanly below it after.

    Adds a regression test asserting the wrapper table carries no float-triggering
    align attribute while retaining text-align.

    Fixes CM-520.

    Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01Dv2sgScyH9Ahv2rd65EuJu

    * test(email-editor): pin RTL wrapper alignment to the wrapper tag, not a substring

    Both the media-text and gallery RTL tests asserted alignment with a bare
    assertStringContainsString( 'align="right"', $rendered ) over the whole render.
    That does not pin the wrapper: the Outlook-only spacer table emitted by
    Abstract_Block_Renderer::add_spacer() carries align="right" inside an
    <!--[if mso | IE]--> conditional comment, so the assertion keeps passing after
    the wrapper's own attribute is removed.

    The gallery test has therefore been passing for the wrong reason since #66833
    removed that attribute, and the media-text test would have started doing the
    same with this branch's fix — in both cases silently dropping the RTL coverage
    the test names claim.

    Assert against the wrapper tag itself instead, via WP_HTML_Tag_Processor: no
    align attribute, and text-align:right in its inline style. Verified both
    assertions fail ("Failed asserting that 'right' is null.") when the attribute
    is reinstated on either renderer.

    Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01Dv2sgScyH9Ahv2rd65EuJu

    ---------

    Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

diff --git a/packages/php/email-editor/changelog/fix-cm-520-media-text-float-button-bleed b/packages/php/email-editor/changelog/fix-cm-520-media-text-float-button-bleed
new file mode 100644
index 00000000000..187303c87e4
--- /dev/null
+++ b/packages/php/email-editor/changelog/fix-cm-520-media-text-float-button-bleed
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Keep Media & Text blocks in normal document flow so a button placed after one no longer paints its background across it. The wrapper table's align="left" rendered as a float in email clients, pulling the block out of flow so the following block failed to clear it. Alignment is preserved via the existing text-align CSS.
diff --git a/packages/php/email-editor/src/Integrations/Core/Renderer/Blocks/class-media-text.php b/packages/php/email-editor/src/Integrations/Core/Renderer/Blocks/class-media-text.php
index 818d341db3f..1246018f7d9 100644
--- a/packages/php/email-editor/src/Integrations/Core/Renderer/Blocks/class-media-text.php
+++ b/packages/php/email-editor/src/Integrations/Core/Renderer/Blocks/class-media-text.php
@@ -101,10 +101,16 @@ class Media_Text extends Abstract_Block_Renderer {
 		);

 		// Apply class and style attributes to the wrapper table.
+		//
+		// Intentionally omit the `align` attribute. `align="left"` (or "right") on a table renders as
+		// `float: left` in email clients, taking the block out of normal flow — the block that follows
+		// then fails to clear it and overlaps it, so a following button paints its background across
+		// the media & text block above. Horizontal alignment is already carried by the `text-align`
+		// declaration in $block_styles['css'], so dropping the attribute preserves alignment while
+		// keeping the block in normal flow. Same fix as the gallery wrapper.
 		$table_attrs = array(
 			'class' => 'email-block-media-text ' . $original_wrapper_classname,
 			'style' => $block_styles['css'],
-			'align' => $rendering_context->get_default_text_align(),
 			'width' => '100%',
 		);

diff --git a/packages/php/email-editor/tests/integration/Integrations/Core/Renderer/Blocks/Core_Renderers_Rtl_Test.php b/packages/php/email-editor/tests/integration/Integrations/Core/Renderer/Blocks/Core_Renderers_Rtl_Test.php
index d373e0f218a..5c966e35636 100644
--- a/packages/php/email-editor/tests/integration/Integrations/Core/Renderer/Blocks/Core_Renderers_Rtl_Test.php
+++ b/packages/php/email-editor/tests/integration/Integrations/Core/Renderer/Blocks/Core_Renderers_Rtl_Test.php
@@ -110,8 +110,7 @@ class Core_Renderers_Rtl_Test extends \Email_Editor_Integration_Test_Case {
 		$this->assertNotFalse( $media_position );
 		$this->assertNotFalse( $text_position );
 		$this->assertLessThan( $text_position, $media_position );
-		$this->assertStringContainsString( 'text-align:right;', $rendered );
-		$this->assertStringContainsString( 'align="right"', $rendered );
+		$this->assertWrapperIsRtlAlignedWithoutFloat( $rendered, 'email-block-media-text' );
 	}

 	/**
@@ -202,8 +201,7 @@ class Core_Renderers_Rtl_Test extends \Email_Editor_Integration_Test_Case {
 			$this->rtl_context
 		);

-		$this->assertStringContainsString( 'text-align:right;', $rendered );
-		$this->assertStringContainsString( 'align="right"', $rendered );
+		$this->assertWrapperIsRtlAlignedWithoutFloat( $rendered, 'email-block-gallery' );
 	}

 	/**
@@ -225,6 +223,40 @@ class Core_Renderers_Rtl_Test extends \Email_Editor_Integration_Test_Case {
 		$this->assertOuterSpacerAligned( $rendered, 'right' );
 	}

+	/**
+	 * Assert that a block's wrapper table carries its RTL alignment as a `text-align` declaration
+	 * rather than as an `align` attribute.
+	 *
+	 * `align="right"` on a table renders as `float: right` in email clients, taking the block out of
+	 * normal flow so the block that follows fails to clear it. Searching the whole render for the
+	 * substring `align="right"` does not pin this down: the Outlook-only spacer table emitted by
+	 * Abstract_Block_Renderer::add_spacer() carries one inside a conditional comment, so such an
+	 * assertion keeps passing after the wrapper's own attribute is gone. Inspect the wrapper tag.
+	 *
+	 * @param string $rendered Rendered HTML.
+	 * @param string $wrapper_class Class identifying the block's wrapper table.
+	 */
+	private function assertWrapperIsRtlAlignedWithoutFloat( string $rendered, string $wrapper_class ): void {
+		$processor = new \WP_HTML_Tag_Processor( $rendered );
+		$this->assertTrue(
+			$processor->next_tag(
+				array(
+					'tag_name'   => 'table',
+					'class_name' => $wrapper_class,
+				)
+			),
+			sprintf( 'Expected a wrapper table with the %s class.', $wrapper_class )
+		);
+
+		// No float-triggering align attribute ( get_attribute() is null when the attribute is absent ).
+		$this->assertNull( $processor->get_attribute( 'align' ) );
+
+		// RTL alignment is carried by the text-align declaration instead, keeping the block in flow.
+		$style = $processor->get_attribute( 'style' );
+		$this->assertIsString( $style );
+		$this->assertStringContainsString( 'text-align:right;', $style );
+	}
+
 	/**
 	 * Assert that the outer spacer wrapper uses the expected alignment.
 	 *
diff --git a/packages/php/email-editor/tests/integration/Integrations/Core/Renderer/Blocks/Media_Text_Test.php b/packages/php/email-editor/tests/integration/Integrations/Core/Renderer/Blocks/Media_Text_Test.php
index a1efd617a41..9e7c883f69b 100644
--- a/packages/php/email-editor/tests/integration/Integrations/Core/Renderer/Blocks/Media_Text_Test.php
+++ b/packages/php/email-editor/tests/integration/Integrations/Core/Renderer/Blocks/Media_Text_Test.php
@@ -76,6 +76,38 @@ class Media_Text_Test extends \Email_Editor_Integration_Test_Case {
 		$this->assertStringContainsString( 'Media content', $rendered );
 	}

+	/**
+	 * The media & text wrapper table must not carry an `align="left"`/`align="right"` attribute: those
+	 * render as `float` in email clients, pulling the block out of normal flow so the block that follows
+	 * fails to clear it. A button placed after it then paints its background across the media & text
+	 * block above. Horizontal alignment must instead come from the `text-align` CSS declaration, which
+	 * keeps the block in normal flow.
+	 */
+	public function testItDoesNotFloatWrapperTableWithAlignAttribute(): void {
+		$rendered = $this->media_renderer->render( '', $this->parsed_media, $this->rendering_context );
+
+		// Locate the wrapper table by its class. Parsing the tag with WP_HTML_Tag_Processor is more
+		// robust than matching the raw HTML string, and matches the convention used elsewhere here.
+		$processor = new \WP_HTML_Tag_Processor( $rendered );
+		$this->assertTrue(
+			$processor->next_tag(
+				array(
+					'tag_name'   => 'table',
+					'class_name' => 'email-block-media-text',
+				)
+			),
+			'Expected a media & text wrapper table with the email-block-media-text class.'
+		);
+
+		// No float-triggering align attribute on the wrapper table ( get_attribute() is null when absent ).
+		$this->assertNull( $processor->get_attribute( 'align' ) );
+
+		// Alignment is preserved via the text-align CSS declaration instead, keeping the block in normal flow.
+		$style = $processor->get_attribute( 'style' );
+		$this->assertIsString( $style );
+		$this->assertStringContainsString( 'text-align', $style );
+	}
+
 	/**
 	 * Test it handles media positioning
 	 */