Commit 9d96517b71f for woocommerce
commit 9d96517b71faaff6f9447fb1e664aa2ea91be435
Author: Ann <annchichi@users.noreply.github.com>
Date: Mon Aug 17 19:04:18 2026 +0800
[Email Editor] Fix social links spacing in rendered emails (#67642)
* Fix social links spacing in rendered emails
* Add changelog entry for social links spacing fix
* Add RTL coverage for social links spacing
* Fix pill shape padding for social link sizes
* Update social links tests to assert individual wrappers
diff --git a/packages/php/email-editor/changelog/fix-social-links-rendered-spacing b/packages/php/email-editor/changelog/fix-social-links-rendered-spacing
new file mode 100644
index 00000000000..243b3df356e
--- /dev/null
+++ b/packages/php/email-editor/changelog/fix-social-links-rendered-spacing
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Render spacing between Social Links icons in emails and match pill-shape icon padding with the editor.
diff --git a/packages/php/email-editor/src/Integrations/Core/Renderer/Blocks/class-social-links.php b/packages/php/email-editor/src/Integrations/Core/Renderer/Blocks/class-social-links.php
index 0d883fc9970..f6ad80c5869 100644
--- a/packages/php/email-editor/src/Integrations/Core/Renderer/Blocks/class-social-links.php
+++ b/packages/php/email-editor/src/Integrations/Core/Renderer/Blocks/class-social-links.php
@@ -44,9 +44,20 @@ class Social_Links extends Abstract_Block_Renderer {
$inner_blocks = $parsed_block['innerBlocks'] ?? array();
- $content = '';
+ $content = '';
+ $is_first_rendered_link = true;
foreach ( $inner_blocks as $block ) {
- $content .= $this->generate_social_link_content( $block, $attrs );
+ $social_link_content = $this->generate_social_link_content(
+ $block,
+ $attrs,
+ ! $is_first_rendered_link,
+ $rendering_context->get_start_side()
+ );
+ if ( '' === $social_link_content ) {
+ continue;
+ }
+ $is_first_rendered_link = false;
+ $content .= $social_link_content;
}
return str_replace(
@@ -59,11 +70,13 @@ class Social_Links extends Abstract_Block_Renderer {
/**
* Generates the social link content.
*
- * @param array $block The block data.
- * @param array $parent_block_attrs The parent block attributes.
+ * @param array $block The block data.
+ * @param array $parent_block_attrs The parent block attributes.
+ * @param bool $render_gap Whether to render a gap before the item.
+ * @param string $gap_side The physical side used for the horizontal gap.
* @return string The generated content.
*/
- private function generate_social_link_content( $block, $parent_block_attrs ) {
+ private function generate_social_link_content( $block, $parent_block_attrs, bool $render_gap = false, string $gap_side = 'left' ) {
$service_name = $block['attrs']['service'] ?? '';
$service_url = $block['attrs']['url'] ?? '';
$label = $block['attrs']['label'] ?? '';
@@ -123,10 +136,11 @@ class Social_Links extends Abstract_Block_Renderer {
$main_table_styles = $this->compile_css(
array(
- 'background-color' => $icon_background_color_value,
- 'border-radius' => '9999px',
- 'display' => 'inline-table',
- 'float' => 'none',
+ 'background-color' => $icon_background_color_value,
+ 'border-radius' => '9999px',
+ 'display' => 'inline-table',
+ 'float' => 'none',
+ 'margin-' . $gap_side => $render_gap ? '16px' : '',
)
);
@@ -154,8 +168,9 @@ class Social_Links extends Abstract_Block_Renderer {
);
if ( $is_pill_shape ) {
- $row_container_styles['padding-left'] = '17px';
- $row_container_styles['padding-right'] = '17px';
+ $pill_shape_horizontal_padding = round( $font_size_value * 2 / 3, 2 ) . 'px';
+ $row_container_styles['padding-left'] = $pill_shape_horizontal_padding;
+ $row_container_styles['padding-right'] = $pill_shape_horizontal_padding;
}
$row_container_styles = $this->compile_css( $row_container_styles );
@@ -207,7 +222,11 @@ class Social_Links extends Abstract_Block_Renderer {
$main_table = Table_Wrapper_Helper::render_table_wrapper( $social_link_content, $main_table_attrs, array(), $main_row_attrs, false );
- return Table_Wrapper_Helper::render_outlook_table_cell( $main_table );
+ $outlook_cell_attrs = array(
+ 'style' => $render_gap ? 'padding-' . $gap_side . ':16px;' : '',
+ );
+
+ return Table_Wrapper_Helper::render_outlook_table_cell( $main_table, $outlook_cell_attrs );
}
/**
diff --git a/packages/php/email-editor/tests/integration/Integrations/Core/Renderer/Blocks/Social_Links_Test.php b/packages/php/email-editor/tests/integration/Integrations/Core/Renderer/Blocks/Social_Links_Test.php
index 20f3e5401a4..4617b8bb377 100644
--- a/packages/php/email-editor/tests/integration/Integrations/Core/Renderer/Blocks/Social_Links_Test.php
+++ b/packages/php/email-editor/tests/integration/Integrations/Core/Renderer/Blocks/Social_Links_Test.php
@@ -119,8 +119,72 @@ class Social_Links_Test extends \Email_Editor_Integration_Test_Case {
$rendered = $this->social_links_renderer->render( '', $parsed_social_links, $this->rendering_context );
$this->checkValidHTML( $rendered );
- $this->assertStringContainsString( 'padding-left:17px;', $rendered );
- $this->assertStringContainsString( 'padding-right:17px;', $rendered );
+ $link_wrappers = $this->getRenderedSocialLinkWrappers( $rendered );
+ foreach ( $link_wrappers as $link_wrapper ) {
+ $this->assertStringContainsString( 'padding-left:16px;', $link_wrapper );
+ $this->assertStringContainsString( 'padding-right:16px;', $link_wrapper );
+ }
+ }
+
+ /**
+ * Test it renders pill shape padding based on the selected icon size.
+ */
+ public function testItRendersSocialLinksWithPillShapePaddingForDifferentSizes(): void {
+ $sizes = array(
+ 'has-small-icon-size' => '10.67px',
+ 'has-normal-icon-size' => '16px',
+ 'has-large-icon-size' => '24px',
+ 'has-huge-icon-size' => '32px',
+ );
+
+ foreach ( $sizes as $size_class => $expected_padding ) {
+ $parsed_social_links = $this->parsed_social_links;
+ $parsed_social_links['attrs']['className'] = 'is-style-pill-shape';
+ $parsed_social_links['attrs']['size'] = $size_class;
+
+ $rendered = $this->social_links_renderer->render( '', $parsed_social_links, $this->rendering_context );
+ $this->checkValidHTML( $rendered );
+ $link_wrappers = $this->getRenderedSocialLinkWrappers( $rendered );
+ foreach ( $link_wrappers as $link_wrapper ) {
+ $this->assertStringContainsString( "padding-left:{$expected_padding};", $link_wrapper );
+ $this->assertStringContainsString( "padding-right:{$expected_padding};", $link_wrapper );
+ }
+ }
+ }
+
+ /**
+ * Test it renders a gap between social link items.
+ */
+ public function testItRendersGapBetweenSocialLinkItems(): void {
+ $parsed_social_links = $this->parsed_social_links;
+ $parsed_social_links['attrs']['className'] = '';
+ $parsed_social_links['attrs']['showLabels'] = false;
+
+ $rendered = $this->social_links_renderer->render( '', $parsed_social_links, $this->rendering_context );
+ $this->checkValidHTML( $rendered );
+ $link_wrappers = $this->getRenderedSocialLinkWrappers( $rendered );
+ $this->assertStringNotContainsString( 'margin-left:16px;', $link_wrappers['facebook'] );
+ $this->assertStringNotContainsString( 'padding-left:16px;', $link_wrappers['facebook'] );
+ $this->assertStringContainsString( 'margin-left:16px;', $link_wrappers['twitter'] );
+ $this->assertStringContainsString( 'padding-left:16px;', $link_wrappers['twitter'] );
+ }
+
+ /**
+ * Test it renders a gap between social link items in RTL.
+ */
+ public function testItRendersRtlGapBetweenSocialLinkItems(): void {
+ $parsed_social_links = $this->parsed_social_links;
+ $parsed_social_links['attrs']['className'] = '';
+ $parsed_social_links['attrs']['showLabels'] = false;
+ $rtl_rendering_context = new Rendering_Context( $this->rendering_context->get_theme_json(), array( 'is_rtl' => true ) );
+
+ $rendered = $this->social_links_renderer->render( '', $parsed_social_links, $rtl_rendering_context );
+ $this->checkValidHTML( $rendered );
+ $link_wrappers = $this->getRenderedSocialLinkWrappers( $rendered );
+ $this->assertStringNotContainsString( 'margin-right:16px;', $link_wrappers['facebook'] );
+ $this->assertStringNotContainsString( 'padding-right:16px;', $link_wrappers['facebook'] );
+ $this->assertStringContainsString( 'margin-right:16px;', $link_wrappers['twitter'] );
+ $this->assertStringContainsString( 'padding-right:16px;', $link_wrappers['twitter'] );
}
/**
@@ -216,4 +280,49 @@ class Social_Links_Test extends \Email_Editor_Integration_Test_Case {
$non_existing_service_icon_url = $this->social_links_renderer->get_service_icon_url( 'non-existing-service' );
$this->assertEquals( '', $non_existing_service_icon_url );
}
+
+ /**
+ * Gets the rendered wrapper fragment for each social link.
+ *
+ * @param string $rendered The rendered social links block.
+ * @return array<string, string>
+ */
+ private function getRenderedSocialLinkWrappers( string $rendered ): array {
+ $urls = array(
+ 'facebook' => 'https://facebook.com',
+ 'twitter' => 'https://twitter.com',
+ );
+
+ $wrapper_starts = array();
+ foreach ( $urls as $service => $url ) {
+ $url_position = strpos( $rendered, 'href="' . $url . '"' );
+ if ( false === $url_position ) {
+ $this->fail( sprintf( 'Expected to find rendered %s social link.', $service ) );
+ }
+
+ $content_before_url = substr( $rendered, 0, $url_position );
+ $wrapper_start = strrpos( $content_before_url, '<!--[if mso | IE]><td' );
+ if ( false === $wrapper_start ) {
+ $this->fail( sprintf( 'Expected to find rendered %s social link wrapper.', $service ) );
+ }
+
+ $wrapper_starts[ $service ] = $wrapper_start;
+ }
+
+ asort( $wrapper_starts );
+
+ $link_wrappers = array();
+ $ordered_services = array_keys( $wrapper_starts );
+ foreach ( $ordered_services as $index => $service ) {
+ $wrapper_start = $wrapper_starts[ $service ];
+ $next_service = $ordered_services[ $index + 1 ] ?? null;
+ $wrapper_end = null === $next_service ? strlen( $rendered ) : $wrapper_starts[ $next_service ];
+
+ $link_wrappers[ $service ] = substr( $rendered, $wrapper_start, $wrapper_end - $wrapper_start );
+ }
+
+ $this->assertCount( 2, $link_wrappers );
+
+ return $link_wrappers;
+ }
}