Repository: woocommerce/woocommerce
Pull request #57973: Product Details: `woocommerce_product_tabs` compatibility layer
Author: login: dinhtungdu
Labels: name: plugin: woocommerce
description: Issues related to the WooCommerce Core plugin.
Created: 2025-05-14T02:37:31Z | Merged: 2025-05-16T00:35:14Z

### Submission Review Guidelines:

-   I have followed the [WooCommerce Contributing Guidelines](https://github.com/woocommerce/woocommerce/blob/trunk/.github/CONTRIBUTING.md) and the [WordPress Coding Standards](https://make.wordpress.org/core/handbook/best-practices/coding-standards/).
-   I have checked to ensure there aren't other open [Pull Requests](https://github.com/woocommerce/woocommerce/pulls) for the same update/change.
-   I have reviewed my code for [security best practices](https://developer.wordpress.org/apis/security/).
-   Following the above guidelines will result in quick merges and clear and detailed feedback when appropriate.

<!-- You can erase any parts of this template not applicable to your Pull Request. -->

### Changes proposed in this Pull Request:

<!-- If necessary, indicate if this PR is part of a bigger feature. Add a label with the format `focus: name of the feature [team:name of the team]`. -->

<!-- Describe the changes made to this Pull Request and the reason for such changes. -->

<!-- For bug fixes: If known, please provide links to help with traceability and escape analysis. -->
<!-- Please include a link to the issue of the bug being fixed, if one doesn't exist please create it. -->
<!-- If the PR that introduced the bug is known, please also add its link below. -->
This PR adds the tabs added through the `woocommerce_product_tabs` block to the new Product Details block. The logic is similar to #54787 but adjusted to work better with https://github.com/woocommerce/woocommerce/pull/57893.

Closes https://github.com/woocommerce/woocommerce/issues/54731
Closes WOOPLUG-3048
Replaces https://github.com/woocommerce/woocommerce/pull/54787

### How to test the changes in this Pull Request:
_Copied from #54787._
1. Edit the Single Product Template.
2. Add `Blockified Product Details` block
3. Customize the block.
4. Save the template.
5. Visit a Single Product page.
6. Ensure that your changes are visible.
7. Install [Code Snippets plugin](https://wordpress.org/plugins/code-snippets/).
8. Visit `/wp-admin/admin.php?page=add-snippet`
9. Copy-paste this code:


```php
		add_filter(
			'woocommerce_product_tabs',
			function ( $tabs ) {
				$tabs['custom_info_tab'] = array(
					'title'    => 'Custom Info',
					'priority' => 50,
					'callback' => function () {
						echo '<p>This is the content for the custom info tab.</p>';
					},
				);

				$tabs['specifications_tab'] = array(
					'title'    => 'Specifications',
					'priority' => 60,
					'callback' => function () {
						echo '<h2>Specifications</h2>';
						echo '<p>Here you can list product specifications.</p>';
					},
				);

				return $tabs;
			}
	);
```

This code adds two new accordions.
10. Visit a Single Product page.
11. Ensure that the new two accordions are added and work fine.

<!-- End testing instructions -->


Diff:
diff --git a/plugins/woocommerce/changelog/try-product-details-compatibility-layer b/plugins/woocommerce/changelog/try-product-details-compatibility-layer
new file mode 100644
index 0000000000000..0271b08c47ae8
--- /dev/null
+++ b/plugins/woocommerce/changelog/try-product-details-compatibility-layer
@@ -0,0 +1,5 @@
+Significance: patch
+Type: add
+Comment: Experimental Product Details: add compatibility layer for woocommerce_product_tabs
+
+
diff --git a/plugins/woocommerce/src/Blocks/BlockTypes/BlockifiedProductDetails.php b/plugins/woocommerce/src/Blocks/BlockTypes/BlockifiedProductDetails.php
index d1213ac7f5928..4ceabe80d070d 100644
--- a/plugins/woocommerce/src/Blocks/BlockTypes/BlockifiedProductDetails.php
+++ b/plugins/woocommerce/src/Blocks/BlockTypes/BlockifiedProductDetails.php
@@ -35,69 +35,227 @@ protected function get_block_type_style() {
 	 * @return string Rendered block output.
 	 */
 	protected function render( $attributes, $content, $block ) {
-		return $this->hide_empty_accordion_items( $content, $block );
+		$parsed_block = $block->parsed_block;
+		$parsed_block = $this->hide_empty_accordion_items( $parsed_block, $block->context );
+
+		/**
+		 * Filter to disable the compatibility layer for the blockified templates.
+		 *
+		 * @see AddToCartWithOptions::render() for full documentation.
+		 * @since 7.6.0
+		 */
+		if ( ! apply_filters( 'woocommerce_disable_compatibility_layer', false ) ) {
+			$parsed_block = $this->inject_compatible_tabs( $parsed_block );
+		}
+
+		$inner_content = array_reduce(
+			$parsed_block['innerBlocks'],
+			function ( $carry, $parsed_inner_block ) use ( $block ) {
+				$carry .= ( new \WP_Block( $parsed_inner_block, $block->context ) )->render();
+				return $carry;
+			},
+			''
+		);
+
+		return sprintf(
+			'<div %1$s>%2$s</div>',
+			get_block_wrapper_attributes(),
+			$inner_content
+		);
 	}
 
 	/**
-	 * Hide empty accordion items.
+	 * Inject compatible tabs.
 	 *
-	 * @param string   $content Block content.
-	 * @param WP_Block $block Block instance.
+	 * @param array $parsed_block Parsed block.
 	 *
-	 * @return string Rendered block output.
+	 * @return array Parsed block.
 	 */
-	private function hide_empty_accordion_items( $content, $block ) {
-		$accordion_items = $this->find_accordion_items( $block->parsed_block );
-
-		if ( ! $accordion_items ) {
-			return $content;
+	private function inject_compatible_tabs( $parsed_block ) {
+		if ( ! $this->has_accordion( $parsed_block ) ) {
+			return $parsed_block;
 		}
 
-		$accordion_items_visibility = array_map(
-			function ( $item ) use ( $block ) {
-				$content_block          = end( $item['innerBlocks'] );
-				$rendered_content_block = ( new WP_Block( $content_block, $block->context ) )->render();
-				$p                      = new WP_HTML_Tag_Processor( $rendered_content_block );
-
-				return $p->next_tag( 'img' ) ||
-					$p->next_tag( 'iframe' ) ||
-					$p->next_tag( 'video' ) ||
-					$p->next_tag( 'meter' ) ||
-					! empty( wp_strip_all_tags( $rendered_content_block, true ) );
-			},
-			$accordion_items
+		/**
+		 * Filter the product tabs in the product details block.
+		 *
+		 * @since 3.3.0
+		 * @param array $tabs Array of product tabs.
+		 */
+		$product_tabs = apply_filters(
+			'woocommerce_product_tabs',
+			array()
+		);
+
+		$default_tabs_callbacks = array(
+			'woocommerce_product_description_tab',
+			'woocommerce_product_additional_information_tab',
+			'comments_template',
 		);
 
-		$p = new WP_HTML_Tag_Processor( $content );
+		$product_tabs = array_filter(
+			$product_tabs,
+			function ( $tab ) use ( $default_tabs_callbacks ) {
+				return ! in_array( $tab['callback'], $default_tabs_callbacks, true );
+			}
+		);
+
+		usort(
+			$product_tabs,
+			function ( $a, $b ) {
+				return $a['priority'] <=> $b['priority'];
+			}
+		);
+
+		$accordion_blocks = array();
+
+		foreach ( $product_tabs as $key => $tab ) {
+			ob_start();
+			call_user_func( $tab['callback'], $key, $tab );
+			$tab_content        = ob_get_clean();
+			$accordion_blocks[] = $this->create_accordion_item_block(
+				$tab['title'],
+				'<!-- wp:html -->' . $tab_content . '<!-- /wp:html -->'
+			);
+		}
+
+		return $this->inject_parsed_accordion_blocks( $parsed_block, $accordion_blocks );
+	}
+
+	/**
+	 * Create an accordion item block.
+	 *
+	 * @param string $title Title of the accordion item.
+	 * @param string $content Content of the accordion item as block markup.
+	 *
+	 * @return array Accordion item.
+	 */
+	private function create_accordion_item_block( $title, $content ) {
+		$template = '<!-- wp:woocommerce/accordion-item -->
+			<div class="wp-block-woocommerce-accordion-item"><!-- wp:woocommerce/accordion-header -->
+			<h3 class="wp-block-woocommerce-accordion-header accordion-item__heading">
+			<button class="accordion-item__toggle">
+			<span>%1$s</span>
+			<span class="accordion-item__toggle-icon has-icon-plus" style="width:1.2em;height:1.2em"><svg width="1.2em" height="1.2em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"><path d="M11 12.5V17.5H12.5V12.5H17.5V11H12.5V6H11V11H6V12.5H11Z" fill="currentColor"></path></svg></span>
+			</button>
+			</h3>
+			<!-- /wp:woocommerce/accordion-header -->
+
+			<!-- wp:woocommerce/accordion-panel -->
+			<div class="wp-block-woocommerce-accordion-panel"><div class="accordion-content__wrapper">
+			%2$s
+			</div></div>
+			<!-- /wp:woocommerce/accordion-panel --></div>
+			<!-- /wp:woocommerce/accordion-item -->';
 
-		$counter = 0;
-		while ( $p->next_tag( array( 'class_name' => 'wp-block-woocommerce-accordion-item' ) ) ) {
-			if ( ! $accordion_items_visibility[ $counter ] ) {
-				$p->set_attribute( 'style', 'display:none;' );
-				$p->set_attribute( 'hidden', true );
+		return parse_blocks( sprintf( $template, $title, $content ) )[0];
+	}
+
+	/**
+	 * Inject parsed accordion blocks.
+	 *
+	 * @param array $parsed_block Parsed block.
+	 * @param array $accordion_blocks Accordion blocks.
+	 *
+	 * @return array Parsed block.
+	 */
+	private function inject_parsed_accordion_blocks( $parsed_block, $accordion_blocks ) {
+		if ( 'woocommerce/accordion-group' === $parsed_block['blockName'] ) {
+			$parsed_block['innerBlocks']  = array_merge( $parsed_block['innerBlocks'], $accordion_blocks );
+			$parsed_block['innerBlocks']  = array_values( array_filter( $parsed_block['innerBlocks'] ) );
+			$opening_tag                  = reset( $parsed_block['innerContent'] );
+			$closing_tag                  = end( $parsed_block['innerContent'] );
+			$parsed_block['innerContent'] = array_merge(
+				array( $opening_tag ),
+				array_fill( 0, count( $parsed_block['innerBlocks'] ), null ),
+				array( $closing_tag )
+			);
+			return $parsed_block;
+		}
+
+		foreach ( $parsed_block['innerBlocks'] as $key => $inner_block ) {
+			$parsed_block['innerBlocks'][ $key ] = $this->inject_parsed_accordion_blocks( $inner_block, $accordion_blocks );
+		}
+
+		return $parsed_block;
+	}
+
+	/**
+	 * Hide empty accordion items.
+	 *
+	 * @param array $parsed_block Parsed block.
+	 * @param array $context Context.
+	 *
+	 * @return array Parsed block.
+	 */
+	private function hide_empty_accordion_items( $parsed_block, $context ) {
+		if ( ! $this->has_accordion( $parsed_block ) ) {
+			return $parsed_block;
+		}
+
+		if ( 'woocommerce/accordion-group' === $parsed_block['blockName'] ) {
+			foreach ( $parsed_block['innerBlocks'] as $key => $inner_block ) {
+				$parsed_block['innerBlocks'][ $key ] = $this->mark_accordion_item_hidden( $inner_block, $context );
 			}
-			++$counter;
+			$parsed_block['innerBlocks']  = array_values( array_filter( $parsed_block['innerBlocks'] ) );
+			$opening_tag                  = reset( $parsed_block['innerContent'] );
+			$closing_tag                  = end( $parsed_block['innerContent'] );
+			$parsed_block['innerContent'] = array_merge(
+				array( $opening_tag ),
+				array_fill( 0, count( $parsed_block['innerBlocks'] ), null ),
+				array( $closing_tag )
+			);
+			return $parsed_block;
+		}
+
+		foreach ( $parsed_block['innerBlocks'] as $key => $inner_block ) {
+			$parsed_block['innerBlocks'][ $key ] = $this->hide_empty_accordion_items( $inner_block, $context );
+		}
+
+		return $parsed_block;
+	}
+
+	/**
+	 * Mark an accordion item as hidden if it has no content.
+	 *
+	 * @param array $item Item to mark.
+	 * @param array $context Context.
+	 *
+	 * @return array Item.
+	 */
+	private function mark_accordion_item_hidden( $item, $context ) {
+		$content_block          = end( $item['innerBlocks'] );
+		$rendered_content_block = ( new WP_Block( $content_block, $context ) )->render();
+		$p                      = new WP_HTML_Tag_Processor( $rendered_content_block );
+
+		$has_content = $p->next_tag( 'img' ) ||
+			$p->next_tag( 'iframe' ) ||
+			$p->next_tag( 'video' ) ||
+			$p->next_tag( 'meter' ) ||
+			! empty( wp_strip_all_tags( $rendered_content_block, true ) );
+
+		if ( ! $has_content ) {
+			return array();
 		}
 
-		return $p->get_updated_html();
+		return $item;
 	}
 
 	/**
-	 * Find accordion items.
+	 * Check if a parsed block has an accordion.
 	 *
-	 * @param array $block Block instance.
+	 * @param array $parsed_block Parsed block.
 	 *
-	 * @return array|false Accordion items.
+	 * @return bool True if the block has an accordion, false otherwise.
 	 */
-	private function find_accordion_items( $block ) {
-		if ( 'woocommerce/accordion-group' === $block['blockName'] ) {
-			return $block['innerBlocks'];
+	private function has_accordion( $parsed_block ) {
+		if ( 'woocommerce/accordion-group' === $parsed_block['blockName'] ) {
+			return true;
 		}
 
-		foreach ( $block['innerBlocks'] as $inner_block ) {
-			$items = $this->find_accordion_items( $inner_block );
-			if ( $items ) {
-				return $items;
+		foreach ( $parsed_block['innerBlocks'] as $inner_block ) {
+			if ( $this->has_accordion( $inner_block ) ) {
+				return true;
 			}
 		}
 
diff --git a/plugins/woocommerce/tests/php/src/Blocks/BlockTypes/BlockifiedProductDetails/BlockifiedProductDetails.php b/plugins/woocommerce/tests/php/src/Blocks/BlockTypes/BlockifiedProductDetails/BlockifiedProductDetails.php
new file mode 100644
index 0000000000000..4aa291e45a2dd
--- /dev/null
+++ b/plugins/woocommerce/tests/php/src/Blocks/BlockTypes/BlockifiedProductDetails/BlockifiedProductDetails.php
@@ -0,0 +1,140 @@
+<?php
+
+declare(strict_types=1);
+namespace Automattic\WooCommerce\Tests\Blocks\BlockTypes\BlockifiedProductDetails;
+
+use WC_Helper_Product;
+
+/**
+ * Tests for the BlockifiedProductDetails block type
+ */
+class BlockifiedProductDetails extends \WP_UnitTestCase {
+
+	/**
+	 * Page ID
+	 *
+	 * @var @string
+	 */
+	private static $page_id;
+
+	/**
+	 * Product
+	 *
+	 * @var @WC_Product
+	 */
+	private static $product;
+
+	/**
+	 * Create Simple Product and Page
+	 */
+	public static function setUpBeforeClass(): void {
+		parent::setUpBeforeClass();
+
+		self::$product = WC_Helper_Product::create_simple_product( false );
+		WC_Helper_Product::create_product_review( self::$product );
+
+		self::$page_id = wp_insert_post(
+			[
+				'post_title'  => 'Test Product Page',
+				'post_type'   => 'page',
+				'post_status' => 'publish',
+			],
+			true
+		);
+	}
+	/**
+	 * Set up product and page for each test
+	 *
+	 * @return void
+	 */
+	public function setUp(): void {
+		parent::setUp();
+		global $post, $product;
+
+		$post = get_post( self::$page_id );
+		setup_postdata( $post );
+		$product            = self::$product;
+		$GLOBALS['product'] = $product;
+	}
+
+	/**
+	 * Reset postdata after each test
+	 *
+	 * @return void
+	 */
+	public function tearDown(): void {
+		parent::tearDown();
+		wp_reset_postdata();
+	}
+
+	/**
+	 * Delete the product and page after all tests
+	 *
+	 * @return void
+	 */
+	public static function tearDownAfterClass(): void {
+		parent::tearDownAfterClass();
+		wp_delete_post( self::$page_id, true );
+		WC_Helper_Product::delete_product( self::$product->get_id() );
+	}
+
+
+	/**
+	 * Test Product Details render function when `woocommerce_product_tabs` hook isn't used
+	 * IMPORTANT: The current test doesn't validate the entire HTML, but only the text content inside the HTML.
+	 * This is because some ids are generated dynamically via wp_unique_id that it is not straightforward to mock.
+	 */
+	public function test_product_details_render_with_no_hook() {
+
+		$template = file_get_contents( __DIR__ . '/test_product_details_render_with_no_hook_template.html' ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
+
+		$serialized_blocks = do_blocks( $template );
+
+		$expected_serialized_blocks                    = file_get_contents( __DIR__ . '/test_product_details_render_with_no_hook_expected_result.html' ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
+		$serialized_blocks_without_whitespace          = wp_strip_all_tags( $serialized_blocks, true );
+		$expected_serialized_blocks_without_whitespace = wp_strip_all_tags( $expected_serialized_blocks, true );
+		$this->assertEquals( $serialized_blocks_without_whitespace, $expected_serialized_blocks_without_whitespace, '' );
+	}
+
+	/**
+	 * Test Product Details render function when `woocommerce_product_tabs` hook is used.
+	 * IMPORTANT: The current test doesn't validate the entire HTML, but only the text content inside the HTML.
+	 * This is because some ids are generated dynamically via wp_unique_id that it is not straightforward to mock.
+	 */
+	public function test_product_details_render_with_hook() {
+		add_filter(
+			'woocommerce_product_tabs',
+			function ( $tabs ) {
+				$tabs['custom_info_tab'] = array(
+					'title'    => 'Custom Info',
+					'priority' => 50,
+					'callback' => function () {
+						echo '<p>This is the content for the custom info tab.</p>';
+					},
+				);
+
+				$tabs['specifications_tab'] = array(
+					'title'    => 'Specifications',
+					'priority' => 60,
+					'callback' => function () {
+						echo '<h2>Specifications</h2>
+						<p>Here you can list product specifications.</p>';
+					},
+				);
+
+				return $tabs;
+			}
+		);
+
+		$template = file_get_contents( __DIR__ . '/test_product_details_render_with_hook_template.html' ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
+
+		$serialized_blocks = do_blocks( $template );
+
+		$expected_serialized_blocks = file_get_contents( __DIR__ . '/test_product_details_render_with_hook_expected_result.html' ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
+
+		$serialized_blocks_without_whitespace          = wp_strip_all_tags( $serialized_blocks, true );
+		$expected_serialized_blocks_without_whitespace = wp_strip_all_tags( $expected_serialized_blocks, true );
+
+		$this->assertEquals( $serialized_blocks_without_whitespace, $expected_serialized_blocks_without_whitespace, '' );
+	}
+}
diff --git a/plugins/woocommerce/tests/php/src/Blocks/BlockTypes/BlockifiedProductDetails/test_product_details_render_with_hook_expected_result.html b/plugins/woocommerce/tests/php/src/Blocks/BlockTypes/BlockifiedProductDetails/test_product_details_render_with_hook_expected_result.html
new file mode 100644
index 0000000000000..cd0a600bac291
--- /dev/null
+++ b/plugins/woocommerce/tests/php/src/Blocks/BlockTypes/BlockifiedProductDetails/test_product_details_render_with_hook_expected_result.html
@@ -0,0 +1,148 @@
+<div data-block-name="woocommerce/blockified-product-details" class="wp-block-woocommerce-blockified-product-details">
+	<div data-block-name="woocommerce/accordion-group"
+		data-wc-context="{&quot;autoclose&quot;:false,&quot;isOpen&quot;:[]}"
+		data-wc-interactive="{&quot;namespace&quot;:&quot;woocommerce\/accordion&quot;}"
+		class="wp-block-woocommerce-accordion-group is-layout-flow wp-block-woocommerce-accordion-group-is-layout-flow">
+		<div data-block-name="woocommerce/accordion-item" data-wc-class--is-open="state.isOpen"
+			data-wc-context="{&quot;id&quot;:&quot;woocommerce-accordion-item-2&quot;,&quot;openByDefault&quot;:false}"
+			data-wc-init="callbacks.initIsOpen"
+			class="wp-block-woocommerce-accordion-item is-layout-flow wp-block-woocommerce-accordion-item-is-layout-flow">
+			<h3
+				class="wp-block-woocommerce-accordion-header accordion-item__heading is-layout-flow wp-block-woocommerce-accordion-header-is-layout-flow">
+				<button aria-controls="woocommerce-accordion-item-2-panel" data-wc-bind--aria-expanded="state.isOpen"
+					data-wc-on--click="actions.toggle" id="woocommerce-accordion-item-2" class="accordion-item__toggle"
+					aria-expanded="false">
+					<span>Description Header</span>
+					<span class="accordion-item__toggle-icon has-icon-plus" style="width:1.2em;height:1.2em">
+						<svg width="1.2em" height="1.2em" viewBox="0 0 24 24" fill="none"
+							xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
+							<path d="M11 12.5V17.5H12.5V12.5H17.5V11H12.5V6H11V11H6V12.5H11Z" fill="currentColor">
+							</path>
+						</svg>
+					</span>
+				</button>
+			</h3>
+			<div aria-labelledby="woocommerce-accordion-item-2" data-wc-bind--inert="!state.isOpen"
+				id="woocommerce-accordion-item-2-panel" role="region" data-block-name="woocommerce/accordion-panel"
+				data-is-selected="true" class="wp-block-woocommerce-accordion-panel" inert="">
+				<div
+					class="accordion-content__wrapper is-layout-flow wp-block-woocommerce-accordion-panel-is-layout-flow">
+					<p>Description Body</p>
+				</div>
+			</div>
+		</div>
+		<div data-block-name="woocommerce/accordion-item" data-wc-class--is-open="state.isOpen"
+			data-wc-context="{&quot;id&quot;:&quot;woocommerce-accordion-item-3&quot;,&quot;openByDefault&quot;:false}"
+			data-wc-init="callbacks.initIsOpen"
+			class="wp-block-woocommerce-accordion-item is-layout-flow wp-block-woocommerce-accordion-item-is-layout-flow">
+			<h3
+				class="wp-block-woocommerce-accordion-header accordion-item__heading is-layout-flow wp-block-woocommerce-accordion-header-is-layout-flow">
+				<button aria-controls="woocommerce-accordion-item-3-panel" data-wc-bind--aria-expanded="state.isOpen"
+					data-wc-on--click="actions.toggle" id="woocommerce-accordion-item-3" class="accordion-item__toggle"
+					aria-expanded="false">
+					<span>Additional Information Header</span>
+					<span class="accordion-item__toggle-icon has-icon-plus" style="width:1.2em;height:1.2em">
+						<svg width="1.2em" height="1.2em" viewBox="0 0 24 24" fill="none"
+							xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
+							<path d="M11 12.5V17.5H12.5V12.5H17.5V11H12.5V6H11V11H6V12.5H11Z" fill="currentColor">
+							</path>
+						</svg>
+					</span>
+				</button>
+			</h3>
+			<div aria-labelledby="woocommerce-accordion-item-3" data-wc-bind--inert="!state.isOpen"
+				id="woocommerce-accordion-item-3-panel" role="region" data-block-name="woocommerce/accordion-panel"
+				class="wp-block-woocommerce-accordion-panel" inert="">
+				<div
+					class="accordion-content__wrapper is-layout-flow wp-block-woocommerce-accordion-panel-is-layout-flow">
+					<p>Additional Information Body</p>
+				</div>
+			</div>
+		</div>
+		<div data-block-name="woocommerce/accordion-item" data-wc-class--is-open="state.isOpen"
+			data-wc-context="{&quot;id&quot;:&quot;woocommerce-accordion-item-4&quot;,&quot;openByDefault&quot;:false}"
+			data-wc-init="callbacks.initIsOpen"
+			class="wp-block-woocommerce-accordion-item is-layout-flow wp-block-woocommerce-accordion-item-is-layout-flow">
+			<h3
+				class="wp-block-woocommerce-accordion-header accordion-item__heading is-layout-flow wp-block-woocommerce-accordion-header-is-layout-flow">
+				<button aria-controls="woocommerce-accordion-item-4-panel" data-wc-bind--aria-expanded="state.isOpen"
+					data-wc-on--click="actions.toggle" id="woocommerce-accordion-item-4" class="accordion-item__toggle"
+					aria-expanded="false">
+					<span>Reviews Header</span>
+					<span class="accordion-item__toggle-icon has-icon-plus" style="width:1.2em;height:1.2em">
+						<svg width="1.2em" height="1.2em" viewBox="0 0 24 24" fill="none"
+							xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
+							<path d="M11 12.5V17.5H12.5V12.5H17.5V11H12.5V6H11V11H6V12.5H11Z" fill="currentColor">
+							</path>
+						</svg>
+					</span>
+				</button>
+			</h3>
+			<div aria-labelledby="woocommerce-accordion-item-4" data-wc-bind--inert="!state.isOpen"
+				id="woocommerce-accordion-item-4-panel" role="region" data-block-name="woocommerce/accordion-panel"
+				class="wp-block-woocommerce-accordion-panel" inert="">
+				<div
+					class="accordion-content__wrapper is-layout-flow wp-block-woocommerce-accordion-panel-is-layout-flow">
+					<p>Reviews Body</p>
+				</div>
+			</div>
+		</div>
+		<div data-block-name="woocommerce/accordion-item" data-wc-class--is-open="state.isOpen"
+			data-wc-context="{&quot;id&quot;:&quot;woocommerce-accordion-item-4&quot;,&quot;openByDefault&quot;:false}"
+			data-wc-init="callbacks.initIsOpen"
+			class="wp-block-woocommerce-accordion-item is-layout-flow wp-block-woocommerce-accordion-item-is-layout-flow">
+			<h3
+				class="wp-block-woocommerce-accordion-header accordion-item__heading is-layout-flow wp-block-woocommerce-accordion-header-is-layout-flow">
+				<button aria-controls="woocommerce-accordion-item-4-panel" data-wc-bind--aria-expanded="state.isOpen"
+					data-wc-on--click="actions.toggle" id="woocommerce-accordion-item-4" class="accordion-item__toggle"
+					aria-expanded="false">
+					<span>Custom Info</span>
+					<span class="accordion-item__toggle-icon has-icon-plus" style="width:1.2em;height:1.2em">
+						<svg width="1.2em" height="1.2em" viewBox="0 0 24 24" fill="none"
+							xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
+							<path d="M11 12.5V17.5H12.5V12.5H17.5V11H12.5V6H11V11H6V12.5H11Z" fill="currentColor">
+							</path>
+						</svg>
+					</span>
+				</button>
+			</h3>
+			<div aria-labelledby="woocommerce-accordion-item-4" data-wc-bind--inert="!state.isOpen"
+				id="woocommerce-accordion-item-4-panel" role="region" data-block-name="woocommerce/accordion-panel"
+				class="wp-block-woocommerce-accordion-panel" inert="">
+				<div
+					class="accordion-content__wrapper is-layout-flow wp-block-woocommerce-accordion-panel-is-layout-flow">
+					<p>This is the content for the custom info tab.</p>
+				</div>
+			</div>
+		</div>
+		<div data-block-name="woocommerce/accordion-item" data-wc-class--is-open="state.isOpen"
+			data-wc-context="{&quot;id&quot;:&quot;woocommerce-accordion-item-4&quot;,&quot;openByDefault&quot;:false}"
+			data-wc-init="callbacks.initIsOpen"
+			class="wp-block-woocommerce-accordion-item is-layout-flow wp-block-woocommerce-accordion-item-is-layout-flow">
+			<h3
+				class="wp-block-woocommerce-accordion-header accordion-item__heading is-layout-flow wp-block-woocommerce-accordion-header-is-layout-flow">
+				<button aria-controls="woocommerce-accordion-item-4-panel" data-wc-bind--aria-expanded="state.isOpen"
+					data-wc-on--click="actions.toggle" id="woocommerce-accordion-item-4" class="accordion-item__toggle"
+					aria-expanded="false">
+					<span>Specifications</span>
+					<span class="accordion-item__toggle-icon has-icon-plus" style="width:1.2em;height:1.2em">
+						<svg width="1.2em" height="1.2em" viewBox="0 0 24 24" fill="none"
+							xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
+							<path d="M11 12.5V17.5H12.5V12.5H17.5V11H12.5V6H11V11H6V12.5H11Z" fill="currentColor">
+							</path>
+						</svg>
+					</span>
+				</button>
+			</h3>
+			<div aria-labelledby="woocommerce-accordion-item-4" data-wc-bind--inert="!state.isOpen"
+				id="woocommerce-accordion-item-4-panel" role="region" data-block-name="woocommerce/accordion-panel"
+				class="wp-block-woocommerce-accordion-panel" inert="">
+				<div
+					class="accordion-content__wrapper is-layout-flow wp-block-woocommerce-accordion-panel-is-layout-flow">
+					<h2>Specifications</h2>
+					<p>Here you can list product specifications.</p>
+				</div>
+			</div>
+		</div>
+	</div>
+</div>
diff --git a/plugins/woocommerce/tests/php/src/Blocks/BlockTypes/BlockifiedProductDetails/test_product_details_render_with_hook_template.html b/plugins/woocommerce/tests/php/src/Blocks/BlockTypes/BlockifiedProductDetails/test_product_details_render_with_hook_template.html
new file mode 100644
index 0000000000000..da2aa8b5998bb
--- /dev/null
+++ b/plugins/woocommerce/tests/php/src/Blocks/BlockTypes/BlockifiedProductDetails/test_product_details_render_with_hook_template.html
@@ -0,0 +1,74 @@
+<!-- wp:woocommerce/blockified-product-details -->
+<div class="wp-block-woocommerce-blockified-product-details"><!-- wp:woocommerce/accordion-group {"autoclose":false} -->
+	<div class="wp-block-woocommerce-accordion-group"><!-- wp:woocommerce/accordion-item {"openByDefault": false} -->
+		<div class="wp-block-woocommerce-accordion-item"><!-- wp:woocommerce/accordion-header -->
+			<h3 class="wp-block-woocommerce-accordion-header accordion-item__heading"><button
+					class="accordion-item__toggle"><span>Description Header</span><span
+						class="accordion-item__toggle-icon has-icon-plus" style="width:1.2em;height:1.2em"><svg
+							width="1.2em" height="1.2em" viewBox="0 0 24 24" fill="none"
+							xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
+							<path d="M11 12.5V17.5H12.5V12.5H17.5V11H12.5V6H11V11H6V12.5H11Z" fill="currentColor">
+							</path>
+						</svg></span></button></h3>
+			<!-- /wp:woocommerce/accordion-header -->
+
+			<!-- wp:woocommerce/accordion-panel -->
+			<div class="wp-block-woocommerce-accordion-panel">
+				<div class="accordion-content__wrapper"><!-- wp:paragraph -->
+					<p>Description Body</p>
+					<!-- /wp:paragraph -->
+				</div>
+			</div>
+			<!-- /wp:woocommerce/accordion-panel -->
+		</div>
+		<!-- /wp:woocommerce/accordion-item -->
+
+		<!-- wp:woocommerce/accordion-item {"openByDefault": false} -->
+		<div class="wp-block-woocommerce-accordion-item"><!-- wp:woocommerce/accordion-header -->
+			<h3 class="wp-block-woocommerce-accordion-header accordion-item__heading"><button
+					class="accordion-item__toggle"><span>Additional Information Header</span><span
+						class="accordion-item__toggle-icon has-icon-plus" style="width:1.2em;height:1.2em"><svg
+							width="1.2em" height="1.2em" viewBox="0 0 24 24" fill="none"
+							xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
+							<path d="M11 12.5V17.5H12.5V12.5H17.5V11H12.5V6H11V11H6V12.5H11Z" fill="currentColor">
+							</path>
+						</svg></span></button></h3>
+			<!-- /wp:woocommerce/accordion-header -->
+
+			<!-- wp:woocommerce/accordion-panel -->
+			<div class="wp-block-woocommerce-accordion-panel">
+				<div class="accordion-content__wrapper"><!-- wp:paragraph -->
+					<p>Additional Information Body</p>
+					<!-- /wp:paragraph -->
+				</div>
+			</div>
+			<!-- /wp:woocommerce/accordion-panel -->
+		</div>
+		<!-- /wp:woocommerce/accordion-item -->
+
+		<!-- wp:woocommerce/accordion-item {"openByDefault": false} -->
+		<div class="wp-block-woocommerce-accordion-item"><!-- wp:woocommerce/accordion-header -->
+			<h3 class="wp-block-woocommerce-accordion-header accordion-item__heading"><button
+					class="accordion-item__toggle"><span>Reviews Header</span><span
+						class="accordion-item__toggle-icon has-icon-plus" style="width:1.2em;height:1.2em"><svg
+							width="1.2em" height="1.2em" viewBox="0 0 24 24" fill="none"
+							xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
+							<path d="M11 12.5V17.5H12.5V12.5H17.5V11H12.5V6H11V11H6V12.5H11Z" fill="currentColor">
+							</path>
+						</svg></span></button></h3>
+			<!-- /wp:woocommerce/accordion-header -->
+
+			<!-- wp:woocommerce/accordion-panel {"isSelected":true} -->
+			<div class="wp-block-woocommerce-accordion-panel">
+				<div class="accordion-content__wrapper"><!-- wp:paragraph -->
+					<p>Reviews Body</p>
+					<!-- /wp:paragraph -->
+				</div>
+			</div>
+			<!-- /wp:woocommerce/accordion-panel -->
+		</div>
+		<!-- /wp:woocommerce/accordion-item -->
+	</div>
+	<!-- /wp:woocommerce/accordion-group -->
+</div>
+<!-- /wp:woocommerce/blockified-product-details -->
diff --git a/plugins/woocommerce/tests/php/src/Blocks/BlockTypes/BlockifiedProductDetails/test_product_details_render_with_no_hook_expected_result.html b/plugins/woocommerce/tests/php/src/Blocks/BlockTypes/BlockifiedProductDetails/test_product_details_render_with_no_hook_expected_result.html
new file mode 100644
index 0000000000000..be989d2bea8a6
--- /dev/null
+++ b/plugins/woocommerce/tests/php/src/Blocks/BlockTypes/BlockifiedProductDetails/test_product_details_render_with_no_hook_expected_result.html
@@ -0,0 +1,91 @@
+<div data-block-name="woocommerce/blockified-product-details" class="wp-block-woocommerce-blockified-product-details">
+	<div data-block-name="woocommerce/accordion-group"
+		data-wc-context="{&quot;autoclose&quot;:false,&quot;isOpen&quot;:[]}"
+		data-wc-interactive="{&quot;namespace&quot;:&quot;woocommerce\/accordion&quot;}"
+		class="wp-block-woocommerce-accordion-group is-layout-flow wp-block-woocommerce-accordion-group-is-layout-flow">
+		<div data-block-name="woocommerce/accordion-item" data-wc-class--is-open="state.isOpen"
+			data-wc-context="{&quot;id&quot;:&quot;woocommerce-accordion-item-2&quot;,&quot;openByDefault&quot;:false}"
+			data-wc-init="callbacks.initIsOpen"
+			class="wp-block-woocommerce-accordion-item is-layout-flow wp-block-woocommerce-accordion-item-is-layout-flow">
+			<h3
+				class="wp-block-woocommerce-accordion-header accordion-item__heading is-layout-flow wp-block-woocommerce-accordion-header-is-layout-flow">
+				<button aria-controls="woocommerce-accordion-item-2-panel" data-wc-bind--aria-expanded="state.isOpen"
+					data-wc-on--click="actions.toggle" id="woocommerce-accordion-item-2" class="accordion-item__toggle"
+					aria-expanded="false">
+					<span>Description Header</span>
+					<span class="accordion-item__toggle-icon has-icon-plus" style="width:1.2em;height:1.2em">
+						<svg width="1.2em" height="1.2em" viewBox="0 0 24 24" fill="none"
+							xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
+							<path d="M11 12.5V17.5H12.5V12.5H17.5V11H12.5V6H11V11H6V12.5H11Z" fill="currentColor">
+							</path>
+						</svg>
+					</span>
+				</button>
+			</h3>
+			<div aria-labelledby="woocommerce-accordion-item-2" data-wc-bind--inert="!state.isOpen"
+				id="woocommerce-accordion-item-2-panel" role="region" data-block-name="woocommerce/accordion-panel"
+				data-is-selected="true" class="wp-block-woocommerce-accordion-panel" inert="">
+				<div
+					class="accordion-content__wrapper is-layout-flow wp-block-woocommerce-accordion-panel-is-layout-flow">
+					<p>Description Body</p>
+				</div>
+			</div>
+		</div>
+		<div data-block-name="woocommerce/accordion-item" data-wc-class--is-open="state.isOpen"
+			data-wc-context="{&quot;id&quot;:&quot;woocommerce-accordion-item-3&quot;,&quot;openByDefault&quot;:false}"
+			data-wc-init="callbacks.initIsOpen"
+			class="wp-block-woocommerce-accordion-item is-layout-flow wp-block-woocommerce-accordion-item-is-layout-flow">
+			<h3
+				class="wp-block-woocommerce-accordion-header accordion-item__heading is-layout-flow wp-block-woocommerce-accordion-header-is-layout-flow">
+				<button aria-controls="woocommerce-accordion-item-3-panel" data-wc-bind--aria-expanded="state.isOpen"
+					data-wc-on--click="actions.toggle" id="woocommerce-accordion-item-3" class="accordion-item__toggle"
+					aria-expanded="false">
+					<span>Additional Information Header</span>
+					<span class="accordion-item__toggle-icon has-icon-plus" style="width:1.2em;height:1.2em">
+						<svg width="1.2em" height="1.2em" viewBox="0 0 24 24" fill="none"
+							xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
+							<path d="M11 12.5V17.5H12.5V12.5H17.5V11H12.5V6H11V11H6V12.5H11Z" fill="currentColor">
+							</path>
+						</svg>
+					</span>
+				</button>
+			</h3>
+			<div aria-labelledby="woocommerce-accordion-item-3" data-wc-bind--inert="!state.isOpen"
+				id="woocommerce-accordion-item-3-panel" role="region" data-block-name="woocommerce/accordion-panel"
+				class="wp-block-woocommerce-accordion-panel" inert="">
+				<div
+					class="accordion-content__wrapper is-layout-flow wp-block-woocommerce-accordion-panel-is-layout-flow">
+					<p>Additional Information Body</p>
+				</div>
+			</div>
+		</div>
+		<div data-block-name="woocommerce/accordion-item" data-wc-class--is-open="state.isOpen"
+			data-wc-context="{&quot;id&quot;:&quot;woocommerce-accordion-item-4&quot;,&quot;openByDefault&quot;:false}"
+			data-wc-init="callbacks.initIsOpen"
+			class="wp-block-woocommerce-accordion-item is-layout-flow wp-block-woocommerce-accordion-item-is-layout-flow">
+			<h3
+				class="wp-block-woocommerce-accordion-header accordion-item__heading is-layout-flow wp-block-woocommerce-accordion-header-is-layout-flow">
+				<button aria-controls="woocommerce-accordion-item-4-panel" data-wc-bind--aria-expanded="state.isOpen"
+					data-wc-on--click="actions.toggle" id="woocommerce-accordion-item-4" class="accordion-item__toggle"
+					aria-expanded="false">
+					<span>Reviews Header</span>
+					<span class="accordion-item__toggle-icon has-icon-plus" style="width:1.2em;height:1.2em">
+						<svg width="1.2em" height="1.2em" viewBox="0 0 24 24" fill="none"
+							xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
+							<path d="M11 12.5V17.5H12.5V12.5H17.5V11H12.5V6H11V11H6V12.5H11Z" fill="currentColor">
+							</path>
+						</svg>
+					</span>
+				</button>
+			</h3>
+			<div aria-labelledby="woocommerce-accordion-item-4" data-wc-bind--inert="!state.isOpen"
+				id="woocommerce-accordion-item-4-panel" role="region" data-block-name="woocommerce/accordion-panel"
+				class="wp-block-woocommerce-accordion-panel" inert="">
+				<div
+					class="accordion-content__wrapper is-layout-flow wp-block-woocommerce-accordion-panel-is-layout-flow">
+					<p>Reviews Body</p>
+				</div>
+			</div>
+		</div>
+	</div>
+</div>
diff --git a/plugins/woocommerce/tests/php/src/Blocks/BlockTypes/BlockifiedProductDetails/test_product_details_render_with_no_hook_template.html b/plugins/woocommerce/tests/php/src/Blocks/BlockTypes/BlockifiedProductDetails/test_product_details_render_with_no_hook_template.html
new file mode 100644
index 0000000000000..c7422f549a494
--- /dev/null
+++ b/plugins/woocommerce/tests/php/src/Blocks/BlockTypes/BlockifiedProductDetails/test_product_details_render_with_no_hook_template.html
@@ -0,0 +1,70 @@
+<!-- wp:woocommerce/blockified-product-details -->
+<div class="wp-block-woocommerce-blockified-product-details">
+	<!-- wp:woocommerce/accordion-group {"autoclose": false} -->
+	<div class="wp-block-woocommerce-accordion-group"><!-- wp:woocommerce/accordion-item {"openByDefault": false} -->
+		<div class="wp-block-woocommerce-accordion-item"><!-- wp:woocommerce/accordion-header -->
+			<h3 class="wp-block-woocommerce-accordion-header accordion-item__heading"><button
+					class="accordion-item__toggle"><span>Description Header</span><span
+						class="accordion-item__toggle-icon has-icon-plus" style="width:1.2em;height:1.2em"><svg
+							width="1.2em" height="1.2em" viewBox="0 0 24 24" fill="none"
+							xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
+							<path d="M11 12.5V17.5H12.5V12.5H17.5V11H12.5V6H11V11H6V12.5H11Z" fill="currentColor">
+							</path>
+						</svg></span></button></h3>
+			<!-- /wp:woocommerce/accordion-header -->
+			<!-- wp:woocommerce/accordion-panel -->
+			<div class="wp-block-woocommerce-accordion-panel">
+				<div class="accordion-content__wrapper"><!-- wp:paragraph -->
+					<p>Description Body</p>
+					<!-- /wp:paragraph -->
+				</div>
+			</div>
+			<!-- /wp:woocommerce/accordion-panel -->
+		</div>
+		<!-- /wp:woocommerce/accordion-item -->
+		<!-- wp:woocommerce/accordion-item {"openByDefault": false} -->
+		<div class="wp-block-woocommerce-accordion-item"><!-- wp:woocommerce/accordion-header -->
+			<h3 class="wp-block-woocommerce-accordion-header accordion-item__heading"><button
+					class="accordion-item__toggle"><span>Additional Information Header</span><span
+						class="accordion-item__toggle-icon has-icon-plus" style="width:1.2em;height:1.2em"><svg
+							width="1.2em" height="1.2em" viewBox="0 0 24 24" fill="none"
+							xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
+							<path d="M11 12.5V17.5H12.5V12.5H17.5V11H12.5V6H11V11H6V12.5H11Z" fill="currentColor">
+							</path>
+						</svg></span></button></h3>
+			<!-- /wp:woocommerce/accordion-header -->
+			<!-- wp:woocommerce/accordion-panel -->
+			<div class="wp-block-woocommerce-accordion-panel">
+				<div class="accordion-content__wrapper"><!-- wp:paragraph -->
+					<p>Additional Information Body</p>
+					<!-- /wp:paragraph -->
+				</div>
+			</div>
+			<!-- /wp:woocommerce/accordion-panel -->
+		</div>
+		<!-- /wp:woocommerce/accordion-item -->
+		<!-- wp:woocommerce/accordion-item {"openByDefault": false} -->
+		<div class="wp-block-woocommerce-accordion-item"><!-- wp:woocommerce/accordion-header -->
+			<h3 class="wp-block-woocommerce-accordion-header accordion-item__heading"><button
+					class="accordion-item__toggle"><span>Reviews Header</span><span
+						class="accordion-item__toggle-icon has-icon-plus" style="width:1.2em;height:1.2em"><svg
+							width="1.2em" height="1.2em" viewBox="0 0 24 24" fill="none"
+							xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
+							<path d="M11 12.5V17.5H12.5V12.5H17.5V11H12.5V6H11V11H6V12.5H11Z" fill="currentColor">
+							</path>
+						</svg></span></button></h3>
+			<!-- /wp:woocommerce/accordion-header -->
+			<!-- wp:woocommerce/accordion-panel {"isSelected":true} -->
+			<div class="wp-block-woocommerce-accordion-panel">
+				<div class="accordion-content__wrapper"><!-- wp:paragraph -->
+					<p>Reviews Body</p>
+					<!-- /wp:paragraph -->
+				</div>
+			</div>
+			<!-- /wp:woocommerce/accordion-panel -->
+		</div>
+		<!-- /wp:woocommerce/accordion-item -->
+	</div>
+	<!-- /wp:woocommerce/accordion-group -->
+</div>
+<!-- /wp:woocommerce/blockified-product-details -->


Reviews:
user: login: kmanijak
body: The changes LGTM and honestly - it works 😄 

<img width="885" alt="image" src="https://github.com/user-attachments/assets/73f60268-f440-43dc-955a-5cdfcfadf3e3" />

Can you tell me if it's more of an experiment still or this is in state for final review?
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-14T09:30:30Z
user: login: dinhtungdu
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-14T09:50:22Z
user: login: dinhtungdu
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-14T09:51:07Z
user: login: gigitux
body: Awesome work! I left just one comment regarding the `create_accordion_item_block`. I didn't understand why we need to run the additional logic. Also, I have the same questions (I don't have an answer) that I mentioned in the https://github.com/woocommerce/woocommerce/pull/54787

The last time that I think that the idea was:

- have one `woocommerce_disable_compatibility_layer` for all the compatibility layer
- restricts users to setting only the header and content without altering the block's default behavior because we are adding a compatibility layer. The "right" way to extend the block is another one.


Moreover, I would add some integration tests, feel free to copy and paste them from https://github.com/woocommerce/woocommerce/pull/54787


state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-14T10:23:06Z
user: login: dinhtungdu
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-15T02:12:22Z
user: login: dinhtungdu
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-15T02:13:11Z
user: login: gigitux
body: Awesome work! 🚀 The Compatibility Layer works as expected:

<img width="965" alt="image" src="https://github.com/user-attachments/assets/fcdb72c0-1ad2-4955-9809-02cda1952779" />

state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-15T07:20:45Z

Review comments:
path: plugins/woocommerce/src/Blocks/BlockTypes/BlockifiedProductDetails.php
user: login: kmanijak
body: Unrelated comment: do you think we could rename the file to `ProductDetailsBlockified.php`? So in the file structure we can see there are two Product Details blocks but one of them Blockified
created_at: 2025-05-14T09:02:53Z
author_association: CONTRIBUTOR
diff_hunk: @@ -35,69 +35,296 @@ protected function get_block_type_style() {
 	 * @return string Rendered block output.
 	 */
 	protected function render( $attributes, $content, $block ) {
-		return $this->hide_empty_accordion_items( $content, $block );
+		$parsed_block = $block->parsed_block;
+		$parsed_block = $this->hide_empty_accordion_items( $parsed_block, $block->context );
+		$parsed_block = $this->inject_compatible_tabs( $parsed_block );
+
+		$inner_content = array_reduce(
+			$parsed_block['innerBlocks'],
+			function ( $carry, $parsed_inner_block ) use ( $block ) {
+				$carry .= ( new \WP_Block( $parsed_inner_block, $block->context ) )->render();
+				return $carry;
+			},
+			''
+		);
+
+		return sprintf(
+			'<div %1$s>%2$s</div>',
+			get_block_wrapper_attributes(),
+			$inner_content
+		);
 	}
 
 	/**
-	 * Hide empty accordion items.
+	 * Inject compatible tabs.
 	 *
-	 * @param string   $content Block content.
-	 * @param WP_Block $block Block instance.
+	 * @param array $parsed_block Parsed block.
 	 *
-	 * @return string Rendered block output.
+	 * @return array Parsed block.
 	 */
-	private function hide_empty_accordion_items( $content, $block ) {
-		$accordion_items = $this->find_accordion_items( $block->parsed_block );
-
-		if ( ! $accordion_items ) {
-			return $content;
+	private function inject_compatible_tabs( $parsed_block ) {
+		if ( ! $this->has_accordion( $parsed_block ) ) {
+			return $parsed_block;
 		}
 
-		$accordion_items_visibility = array_map(
-			function ( $item ) use ( $block ) {
-				$content_block          = end( $item['innerBlocks'] );
-				$rendered_content_block = ( new WP_Block( $content_block, $block->context ) )->render();
-				$p                      = new WP_HTML_Tag_Processor( $rendered_content_block );
-
-				return $p->next_tag( 'img' ) ||
-					$p->next_tag( 'iframe' ) ||
-					$p->next_tag( 'video' ) ||
-					$p->next_tag( 'meter' ) ||
-					! empty( wp_strip_all_tags( $rendered_content_block, true ) );
-			},
-			$accordion_items
+		/**
+		 * Filter the product tabs in the product details block.
+		 *
+		 * @since 3.3.0
+		 * @param array $tabs Array of product tabs.
+		 */
+		$product_tabs = apply_filters(
+			'woocommerce_product_tabs',
+			array()
 		);
 
-		$p = new WP_HTML_Tag_Processor( $content );
+		$default_tabs_callbacks = array(
+			'woocommerce_product_description_tab',
+			'woocommerce_product_additional_information_tab',
+			'comments_template',
+		);
 
-		$counter = 0;
-		while ( $p->next_tag( array( 'class_name' => 'wp-block-woocommerce-accordion-item' ) ) ) {
-			if ( ! $accordion_items_visibility[ $counter ] ) {
-				$p->set_attribute( 'style', 'display:none;' );
-				$p->set_attribute( 'hidden', true );
+		$product_tabs = array_filter(
+			$product_tabs,
+			function ( $tab ) use ( $default_tabs_callbacks ) {
+				return ! in_array( $tab['callback'], $default_tabs_callbacks, true );
 			}
-			++$counter;
+		);
+
+		usort(
+			$product_tabs,
+			function ( $a, $b ) {
+				return $a['priority'] <=> $b['priority'];
+			}
+		);
+
+		$accordion_blocks = array();
+
+		foreach ( $product_tabs as $key => $tab ) {
+			ob_start();
+			call_user_func( $tab['callback'], $key, $tab );
+			$tab_content        = ob_get_clean();
+			$accordion_blocks[] = $this->create_accordion_item_from_template(
+				$this->get_accordion_item_template( $parsed_block ),
+				$tab['title'],
+				'<!-- wp:html -->' . $tab_content . '<!-- /wp:html -->'
+			);
+		}
+
+		return $this->inject_parsed_accordion_blocks( $parsed_block, $accordion_blocks );
+	}
+
+	/**
+	 * Create an accordion item from a template.
+	 *
+	 * @param array  $template Template.
+	 * @param string $title Title.
+	 * @param string $content Content.
+	 *
+	 * @return array Accordion item.
+	 */
+	private function create_accordion_item_from_template( $template, $title, $content ) {
+		foreach ( $template['innerBlocks'] as &$block ) {
+			if ( 'woocommerce/accordion-header' === $block['blockName'] ) {
+				$block['innerContent'] = array_map(
+					function ( $inner_content ) use ( $title ) {
+						return str_replace( '{{title}}', $title, $inner_content );
+					},
+					$block['innerContent']
+				);
+			}
+			if ( 'woocommerce/accordion-panel' === $block['blockName'] ) {
+				$block['innerBlocks']  = parse_blocks( $content );
+				$openning_tag          = reset( $block['innerContent'] );
+				$closing_tag           = end( $block['innerContent'] );
+				$block['innerContent'] = array_merge(
+					array( $openning_tag ),
+					array_fill( 0, count( $block['innerBlocks'] ), null ),
+					array( $closing_tag )
+				);
+			}
+		}
+
+		return $template;
+	}
+
+	/**
+	 * Get the accordion item template.
+	 *
+	 * @param array $parsed_block Parsed block.
+	 *
+	 * @return array Accordion item template.
+	 */
+	private function get_accordion_item_template( $parsed_block ) {
+		$current_accordion_item = $this->get_current_accordion_item( $parsed_block );
+
+		$default_template = parse_blocks(
+			'<!-- wp:woocommerce/accordion-item -->
+			<div class="wp-block-woocommerce-accordion-item"><!-- wp:woocommerce/accordion-header -->
+			<h3 class="wp-block-woocommerce-accordion-header accordion-item__heading"><button class="accordion-item__toggle"><span>{{title}}</span><span class="accordion-item__toggle-icon has-icon-plus" style="width:1.2em;height:1.2em"><svg width="1.2em" height="1.2em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"><path d="M11 12.5V17.5H12.5V12.5H17.5V11H12.5V6H11V11H6V12.5H11Z" fill="currentColor"></path></svg></span></button></h3>
+			<!-- /wp:woocommerce/accordion-header -->
+
+			<!-- wp:woocommerce/accordion-panel -->
+			<div class="wp-block-woocommerce-accordion-panel"><div class="accordion-content__wrapper">
+			<!-- wp:paragraph --><p>{{content}}</p><!-- /wp:paragraph -->
+			</div></div>
+			<!-- /wp:woocommerce/accordion-panel --></div>
+			<!-- /wp:woocommerce/accordion-item -->'
+		)[0];
+
+		if ( ! $current_accordion_item ) {
+			return $default_template;
+		}
+
+		foreach ( $current_accordion_item['innerBlocks'] as &$inner_block ) {
+			if ( 'woocommerce/accordion-header' === $inner_block['blockName'] ) {
+				$inner_block['innerContent'] = array_map(
+					function ( $inner_content ) {
+						return preg_replace( '/<span>.*?<\/span>/', '<span>{{title}}</span>', $inner_content );
+					},
+					$inner_block['innerContent']
+				);
+			}
+			/**
+			 * If the accordion panel is empty, the innerContent will be a single string item with
+			 * both opening and closing tags. We need to replace it with the default template for
+			 * create_accordion_item_from_template.
+			 */
+			if ( 'woocommerce/accordion-panel' === $inner_block['blockName'] && empty( $inner_block['innerBlocks'] ) ) {
+				$inner_block['innerContent'] = $default_template['innerBlocks'][1]['innerContent'];
+			}
+		}
+
+		return $current_accordion_item;
+	}
+
+	/**
+	 * Get the current accordion item.
+	 *
+	 * @param array $parsed_block Parsed block.
+	 *
+	 * @return array Current accordion item.
path: plugins/woocommerce/src/Blocks/BlockTypes/BlockifiedProductDetails.php
user: login: kmanijak
body: ```suggestion
	 * @return array|false Current accordion item.
```

or you can return an empty array in line 220 instead.
created_at: 2025-05-14T09:06:45Z
author_association: CONTRIBUTOR
diff_hunk: @@ -35,69 +35,296 @@ protected function get_block_type_style() {
 	 * @return string Rendered block output.
 	 */
 	protected function render( $attributes, $content, $block ) {
-		return $this->hide_empty_accordion_items( $content, $block );
+		$parsed_block = $block->parsed_block;
+		$parsed_block = $this->hide_empty_accordion_items( $parsed_block, $block->context );
+		$parsed_block = $this->inject_compatible_tabs( $parsed_block );
+
+		$inner_content = array_reduce(
+			$parsed_block['innerBlocks'],
+			function ( $carry, $parsed_inner_block ) use ( $block ) {
+				$carry .= ( new \WP_Block( $parsed_inner_block, $block->context ) )->render();
+				return $carry;
+			},
+			''
+		);
+
+		return sprintf(
+			'<div %1$s>%2$s</div>',
+			get_block_wrapper_attributes(),
+			$inner_content
+		);
 	}
 
 	/**
-	 * Hide empty accordion items.
+	 * Inject compatible tabs.
 	 *
-	 * @param string   $content Block content.
-	 * @param WP_Block $block Block instance.
+	 * @param array $parsed_block Parsed block.
 	 *
-	 * @return string Rendered block output.
+	 * @return array Parsed block.
 	 */
-	private function hide_empty_accordion_items( $content, $block ) {
-		$accordion_items = $this->find_accordion_items( $block->parsed_block );
-
-		if ( ! $accordion_items ) {
-			return $content;
+	private function inject_compatible_tabs( $parsed_block ) {
+		if ( ! $this->has_accordion( $parsed_block ) ) {
+			return $parsed_block;
 		}
 
-		$accordion_items_visibility = array_map(
-			function ( $item ) use ( $block ) {
-				$content_block          = end( $item['innerBlocks'] );
-				$rendered_content_block = ( new WP_Block( $content_block, $block->context ) )->render();
-				$p                      = new WP_HTML_Tag_Processor( $rendered_content_block );
-
-				return $p->next_tag( 'img' ) ||
-					$p->next_tag( 'iframe' ) ||
-					$p->next_tag( 'video' ) ||
-					$p->next_tag( 'meter' ) ||
-					! empty( wp_strip_all_tags( $rendered_content_block, true ) );
-			},
-			$accordion_items
+		/**
+		 * Filter the product tabs in the product details block.
+		 *
+		 * @since 3.3.0
+		 * @param array $tabs Array of product tabs.
+		 */
+		$product_tabs = apply_filters(
+			'woocommerce_product_tabs',
+			array()
 		);
 
-		$p = new WP_HTML_Tag_Processor( $content );
+		$default_tabs_callbacks = array(
+			'woocommerce_product_description_tab',
+			'woocommerce_product_additional_information_tab',
+			'comments_template',
+		);
 
-		$counter = 0;
-		while ( $p->next_tag( array( 'class_name' => 'wp-block-woocommerce-accordion-item' ) ) ) {
-			if ( ! $accordion_items_visibility[ $counter ] ) {
-				$p->set_attribute( 'style', 'display:none;' );
-				$p->set_attribute( 'hidden', true );
+		$product_tabs = array_filter(
+			$product_tabs,
+			function ( $tab ) use ( $default_tabs_callbacks ) {
+				return ! in_array( $tab['callback'], $default_tabs_callbacks, true );
 			}
-			++$counter;
+		);
+
+		usort(
+			$product_tabs,
+			function ( $a, $b ) {
+				return $a['priority'] <=> $b['priority'];
+			}
+		);
+
+		$accordion_blocks = array();
+
+		foreach ( $product_tabs as $key => $tab ) {
+			ob_start();
+			call_user_func( $tab['callback'], $key, $tab );
+			$tab_content        = ob_get_clean();
+			$accordion_blocks[] = $this->create_accordion_item_from_template(
+				$this->get_accordion_item_template( $parsed_block ),
+				$tab['title'],
+				'<!-- wp:html -->' . $tab_content . '<!-- /wp:html -->'
+			);
+		}
+
+		return $this->inject_parsed_accordion_blocks( $parsed_block, $accordion_blocks );
+	}
+
+	/**
+	 * Create an accordion item from a template.
+	 *
+	 * @param array  $template Template.
+	 * @param string $title Title.
+	 * @param string $content Content.
+	 *
+	 * @return array Accordion item.
+	 */
+	private function create_accordion_item_from_template( $template, $title, $content ) {
+		foreach ( $template['innerBlocks'] as &$block ) {
+			if ( 'woocommerce/accordion-header' === $block['blockName'] ) {
+				$block['innerContent'] = array_map(
+					function ( $inner_content ) use ( $title ) {
+						return str_replace( '{{title}}', $title, $inner_content );
+					},
+					$block['innerContent']
+				);
+			}
+			if ( 'woocommerce/accordion-panel' === $block['blockName'] ) {
+				$block['innerBlocks']  = parse_blocks( $content );
+				$openning_tag          = reset( $block['innerContent'] );
+				$closing_tag           = end( $block['innerContent'] );
+				$block['innerContent'] = array_merge(
+					array( $openning_tag ),
+					array_fill( 0, count( $block['innerBlocks'] ), null ),
+					array( $closing_tag )
+				);
+			}
+		}
+
+		return $template;
+	}
+
+	/**
+	 * Get the accordion item template.
+	 *
+	 * @param array $parsed_block Parsed block.
+	 *
+	 * @return array Accordion item template.
+	 */
+	private function get_accordion_item_template( $parsed_block ) {
+		$current_accordion_item = $this->get_current_accordion_item( $parsed_block );
+
+		$default_template = parse_blocks(
+			'<!-- wp:woocommerce/accordion-item -->
+			<div class="wp-block-woocommerce-accordion-item"><!-- wp:woocommerce/accordion-header -->
+			<h3 class="wp-block-woocommerce-accordion-header accordion-item__heading"><button class="accordion-item__toggle"><span>{{title}}</span><span class="accordion-item__toggle-icon has-icon-plus" style="width:1.2em;height:1.2em"><svg width="1.2em" height="1.2em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"><path d="M11 12.5V17.5H12.5V12.5H17.5V11H12.5V6H11V11H6V12.5H11Z" fill="currentColor"></path></svg></span></button></h3>
+			<!-- /wp:woocommerce/accordion-header -->
+
+			<!-- wp:woocommerce/accordion-panel -->
+			<div class="wp-block-woocommerce-accordion-panel"><div class="accordion-content__wrapper">
+			<!-- wp:paragraph --><p>{{content}}</p><!-- /wp:paragraph -->
+			</div></div>
+			<!-- /wp:woocommerce/accordion-panel --></div>
+			<!-- /wp:woocommerce/accordion-item -->'
+		)[0];
+
+		if ( ! $current_accordion_item ) {
+			return $default_template;
+		}
+
+		foreach ( $current_accordion_item['innerBlocks'] as &$inner_block ) {
+			if ( 'woocommerce/accordion-header' === $inner_block['blockName'] ) {
+				$inner_block['innerContent'] = array_map(
+					function ( $inner_content ) {
+						return preg_replace( '/<span>.*?<\/span>/', '<span>{{title}}</span>', $inner_content );
+					},
+					$inner_block['innerContent']
+				);
+			}
+			/**
+			 * If the accordion panel is empty, the innerContent will be a single string item with
+			 * both opening and closing tags. We need to replace it with the default template for
+			 * create_accordion_item_from_template.
+			 */
+			if ( 'woocommerce/accordion-panel' === $inner_block['blockName'] && empty( $inner_block['innerBlocks'] ) ) {
+				$inner_block['innerContent'] = $default_template['innerBlocks'][1]['innerContent'];
+			}
+		}
+
+		return $current_accordion_item;
+	}
+
+	/**
+	 * Get the current accordion item.
+	 *
+	 * @param array $parsed_block Parsed block.
+	 *
+	 * @return array Current accordion item.
path: plugins/woocommerce/src/Blocks/BlockTypes/BlockifiedProductDetails.php
user: login: dinhtungdu
body: I removed this in [9ecc027](https://github.com/woocommerce/woocommerce/pull/57973/commits/9ecc0274884ab568b40fb7c23db5fc72dfa1dda9)
created_at: 2025-05-14T09:50:22Z
author_association: MEMBER
path: plugins/woocommerce/src/Blocks/BlockTypes/BlockifiedProductDetails.php
user: login: dinhtungdu
body: Yeah, we can do it when we have a final name for this block. I don't think we will stick with `Blockified` for release :D.
created_at: 2025-05-14T09:51:07Z
author_association: MEMBER
diff_hunk: @@ -35,69 +35,236 @@ protected function get_block_type_style() {
 	 * @return string Rendered block output.
 	 */
 	protected function render( $attributes, $content, $block ) {
-		return $this->hide_empty_accordion_items( $content, $block );
+		$parsed_block = $block->parsed_block;
+		$parsed_block = $this->hide_empty_accordion_items( $parsed_block, $block->context );
+		$parsed_block = $this->inject_compatible_tabs( $parsed_block );
+
+		$inner_content = array_reduce(
+			$parsed_block['innerBlocks'],
+			function ( $carry, $parsed_inner_block ) use ( $block ) {
+				$carry .= ( new \WP_Block( $parsed_inner_block, $block->context ) )->render();
+				return $carry;
+			},
+			''
+		);
+
+		return sprintf(
+			'<div %1$s>%2$s</div>',
+			get_block_wrapper_attributes(),
+			$inner_content
+		);
 	}
 
 	/**
-	 * Hide empty accordion items.
+	 * Inject compatible tabs.
 	 *
-	 * @param string   $content Block content.
-	 * @param WP_Block $block Block instance.
+	 * @param array $parsed_block Parsed block.
 	 *
-	 * @return string Rendered block output.
+	 * @return array Parsed block.
 	 */
-	private function hide_empty_accordion_items( $content, $block ) {
-		$accordion_items = $this->find_accordion_items( $block->parsed_block );
-
-		if ( ! $accordion_items ) {
-			return $content;
+	private function inject_compatible_tabs( $parsed_block ) {
+		if ( ! $this->has_accordion( $parsed_block ) ) {
+			return $parsed_block;
 		}
 
-		$accordion_items_visibility = array_map(
-			function ( $item ) use ( $block ) {
-				$content_block          = end( $item['innerBlocks'] );
-				$rendered_content_block = ( new WP_Block( $content_block, $block->context ) )->render();
-				$p                      = new WP_HTML_Tag_Processor( $rendered_content_block );
-
-				return $p->next_tag( 'img' ) ||
-					$p->next_tag( 'iframe' ) ||
-					$p->next_tag( 'video' ) ||
-					$p->next_tag( 'meter' ) ||
-					! empty( wp_strip_all_tags( $rendered_content_block, true ) );
-			},
-			$accordion_items
+		/**
+		 * Filter the product tabs in the product details block.
+		 *
+		 * @since 3.3.0
+		 * @param array $tabs Array of product tabs.
+		 */
+		$product_tabs = apply_filters(
+			'woocommerce_product_tabs',
+			array()
+		);
+
+		$default_tabs_callbacks = array(
+			'woocommerce_product_description_tab',
+			'woocommerce_product_additional_information_tab',
+			'comments_template',
+		);
+
+		$product_tabs = array_filter(
+			$product_tabs,
+			function ( $tab ) use ( $default_tabs_callbacks ) {
+				return ! in_array( $tab['callback'], $default_tabs_callbacks, true );
+			}
 		);
 
-		$p = new WP_HTML_Tag_Processor( $content );
+		usort(
+			$product_tabs,
+			function ( $a, $b ) {
+				return $a['priority'] <=> $b['priority'];
+			}
+		);
+
+		$accordion_blocks = array();
+
+		foreach ( $product_tabs as $key => $tab ) {
+			ob_start();
+			call_user_func( $tab['callback'], $key, $tab );
+			$tab_content        = ob_get_clean();
+			$accordion_blocks[] = $this->create_accordion_item_block(
+				$tab['title'],
+				'<!-- wp:html -->' . $tab_content . '<!-- /wp:html -->'
+			);
+		}
+
+		return $this->inject_parsed_accordion_blocks( $parsed_block, $accordion_blocks );
+	}
+
+	/**
+	 * Create an accordion item block.
+	 *
+	 * @param string $title Title of the accordion item.
+	 * @param string $content Content of the accordion item as block markup.
+	 *
+	 * @return array Accordion item.
+	 */
+	private function create_accordion_item_block( $title, $content ) {
+		$template = parse_blocks(
+			'<!-- wp:woocommerce/accordion-item -->
+			<div class="wp-block-woocommerce-accordion-item"><!-- wp:woocommerce/accordion-header -->
+			<h3 class="wp-block-woocommerce-accordion-header accordion-item__heading"><button class="accordion-item__toggle"><span>{{title}}</span><span class="accordion-item__toggle-icon has-icon-plus" style="width:1.2em;height:1.2em"><svg width="1.2em" height="1.2em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"><path d="M11 12.5V17.5H12.5V12.5H17.5V11H12.5V6H11V11H6V12.5H11Z" fill="currentColor"></path></svg></span></button></h3>
+			<!-- /wp:woocommerce/accordion-header -->
+
+			<!-- wp:woocommerce/accordion-panel -->
+			<div class="wp-block-woocommerce-accordion-panel"><div class="accordion-content__wrapper">
+			<!-- wp:paragraph --><p>{{content}}</p><!-- /wp:paragraph -->
+			</div></div>
+			<!-- /wp:woocommerce/accordion-panel --></div>
+			<!-- /wp:woocommerce/accordion-item -->'
+		)[0];
+
+		foreach ( $template['innerBlocks'] as &$block ) {
+			if ( 'woocommerce/accordion-header' === $block['blockName'] ) {
+				$block['innerContent'] = array_map(
+					function ( $inner_content ) use ( $title ) {
+						return str_replace( '{{title}}', $title, $inner_content );
+					},
+					$block['innerContent']
+				);
+			}
+			if ( 'woocommerce/accordion-panel' === $block['blockName'] ) {
+				$block['innerBlocks']  = parse_blocks( $content );
+				$openning_tag          = reset( $block['innerContent'] );
+				$closing_tag           = end( $block['innerContent'] );
+				$block['innerContent'] = array_merge(
+					array( $openning_tag ),
+					array_fill( 0, count( $block['innerBlocks'] ), null ),
+					array( $closing_tag )
+				);
+			}
+		}
+
+		return $template;
+	}
+
+	/**
+	 * Inject parsed accordion blocks.
+	 *
+	 * @param array $parsed_block Parsed block.
+	 * @param array $accordion_blocks Accordion blocks.
+	 *
+	 * @return array Parsed block.
+	 */
+	private function inject_parsed_accordion_blocks( $parsed_block, $accordion_blocks ) {
+		if ( 'woocommerce/accordion-group' === $parsed_block['blockName'] ) {
+			$parsed_block['innerBlocks']  = array_merge( $parsed_block['innerBlocks'], $accordion_blocks );
+			$parsed_block['innerBlocks']  = array_values( array_filter( $parsed_block['innerBlocks'] ) );
+			$openning_tag                 = reset( $parsed_block['innerContent'] );
+			$closing_tag                  = end( $parsed_block['innerContent'] );
+			$parsed_block['innerContent'] = array_merge(
+				array( $openning_tag ),
+				array_fill( 0, count( $parsed_block['innerBlocks'] ), null ),
+				array( $closing_tag )
+			);
+			return $parsed_block;
+		}
+
+		foreach ( $parsed_block['innerBlocks'] as $key => $inner_block ) {
+			$parsed_block['innerBlocks'][ $key ] = $this->inject_parsed_accordion_blocks( $inner_block, $accordion_blocks );
+		}
+
+		return $parsed_block;
+	}
+
+	/**
+	 * Hide empty accordion items.
+	 *
+	 * @param array $parsed_block Parsed block.
+	 * @param array $context Context.
+	 *
+	 * @return array Parsed block.
+	 */
+	private function hide_empty_accordion_items( $parsed_block, $context ) {
+		if ( ! $this->has_accordion( $parsed_block ) ) {
+			return $parsed_block;
+		}
 
-		$counter = 0;
-		while ( $p->next_tag( array( 'class_name' => 'wp-block-woocommerce-accordion-item' ) ) ) {
-			if ( ! $accordion_items_visibility[ $counter ] ) {
-				$p->set_attribute( 'style', 'display:none;' );
-				$p->set_attribute( 'hidden', true );
+		if ( 'woocommerce/accordion-group' === $parsed_block['blockName'] ) {
+			foreach ( $parsed_block['innerBlocks'] as $key => $inner_block ) {
+				$parsed_block['innerBlocks'][ $key ] = $this->mark_accordion_item_hidden( $inner_block, $context );
 			}
-			++$counter;
+			$parsed_block['innerBlocks']  = array_values( array_filter( $parsed_block['innerBlocks'] ) );
+			$openning_tag                 = reset( $parsed_block['innerContent'] );
path: plugins/woocommerce/src/Blocks/BlockTypes/BlockifiedProductDetails.php
user: login: gigitux
body: I guess that there is a typo. Should it be: 
```suggestion
			$opening_tag                 = reset( $parsed_block['innerContent'] );
```
created_at: 2025-05-14T10:10:31Z
author_association: CONTRIBUTOR
diff_hunk: @@ -35,69 +35,236 @@ protected function get_block_type_style() {
 	 * @return string Rendered block output.
 	 */
 	protected function render( $attributes, $content, $block ) {
-		return $this->hide_empty_accordion_items( $content, $block );
+		$parsed_block = $block->parsed_block;
+		$parsed_block = $this->hide_empty_accordion_items( $parsed_block, $block->context );
+		$parsed_block = $this->inject_compatible_tabs( $parsed_block );
+
+		$inner_content = array_reduce(
+			$parsed_block['innerBlocks'],
+			function ( $carry, $parsed_inner_block ) use ( $block ) {
+				$carry .= ( new \WP_Block( $parsed_inner_block, $block->context ) )->render();
+				return $carry;
+			},
+			''
+		);
+
+		return sprintf(
+			'<div %1$s>%2$s</div>',
+			get_block_wrapper_attributes(),
+			$inner_content
+		);
 	}
 
 	/**
-	 * Hide empty accordion items.
+	 * Inject compatible tabs.
 	 *
-	 * @param string   $content Block content.
-	 * @param WP_Block $block Block instance.
+	 * @param array $parsed_block Parsed block.
 	 *
-	 * @return string Rendered block output.
+	 * @return array Parsed block.
 	 */
-	private function hide_empty_accordion_items( $content, $block ) {
-		$accordion_items = $this->find_accordion_items( $block->parsed_block );
-
-		if ( ! $accordion_items ) {
-			return $content;
+	private function inject_compatible_tabs( $parsed_block ) {
+		if ( ! $this->has_accordion( $parsed_block ) ) {
+			return $parsed_block;
 		}
 
-		$accordion_items_visibility = array_map(
-			function ( $item ) use ( $block ) {
-				$content_block          = end( $item['innerBlocks'] );
-				$rendered_content_block = ( new WP_Block( $content_block, $block->context ) )->render();
-				$p                      = new WP_HTML_Tag_Processor( $rendered_content_block );
-
-				return $p->next_tag( 'img' ) ||
-					$p->next_tag( 'iframe' ) ||
-					$p->next_tag( 'video' ) ||
-					$p->next_tag( 'meter' ) ||
-					! empty( wp_strip_all_tags( $rendered_content_block, true ) );
-			},
-			$accordion_items
+		/**
+		 * Filter the product tabs in the product details block.
+		 *
+		 * @since 3.3.0
+		 * @param array $tabs Array of product tabs.
+		 */
+		$product_tabs = apply_filters(
+			'woocommerce_product_tabs',
+			array()
+		);
+
+		$default_tabs_callbacks = array(
+			'woocommerce_product_description_tab',
+			'woocommerce_product_additional_information_tab',
+			'comments_template',
+		);
+
+		$product_tabs = array_filter(
+			$product_tabs,
+			function ( $tab ) use ( $default_tabs_callbacks ) {
+				return ! in_array( $tab['callback'], $default_tabs_callbacks, true );
+			}
 		);
 
-		$p = new WP_HTML_Tag_Processor( $content );
+		usort(
+			$product_tabs,
+			function ( $a, $b ) {
+				return $a['priority'] <=> $b['priority'];
+			}
+		);
+
+		$accordion_blocks = array();
+
+		foreach ( $product_tabs as $key => $tab ) {
+			ob_start();
+			call_user_func( $tab['callback'], $key, $tab );
+			$tab_content        = ob_get_clean();
+			$accordion_blocks[] = $this->create_accordion_item_block(
+				$tab['title'],
+				'<!-- wp:html -->' . $tab_content . '<!-- /wp:html -->'
+			);
+		}
+
+		return $this->inject_parsed_accordion_blocks( $parsed_block, $accordion_blocks );
+	}
+
+	/**
+	 * Create an accordion item block.
+	 *
+	 * @param string $title Title of the accordion item.
+	 * @param string $content Content of the accordion item as block markup.
+	 *
+	 * @return array Accordion item.
+	 */
+	private function create_accordion_item_block( $title, $content ) {
+		$template = parse_blocks(
+			'<!-- wp:woocommerce/accordion-item -->
+			<div class="wp-block-woocommerce-accordion-item"><!-- wp:woocommerce/accordion-header -->
+			<h3 class="wp-block-woocommerce-accordion-header accordion-item__heading"><button class="accordion-item__toggle"><span>{{title}}</span><span class="accordion-item__toggle-icon has-icon-plus" style="width:1.2em;height:1.2em"><svg width="1.2em" height="1.2em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"><path d="M11 12.5V17.5H12.5V12.5H17.5V11H12.5V6H11V11H6V12.5H11Z" fill="currentColor"></path></svg></span></button></h3>
+			<!-- /wp:woocommerce/accordion-header -->
+
+			<!-- wp:woocommerce/accordion-panel -->
+			<div class="wp-block-woocommerce-accordion-panel"><div class="accordion-content__wrapper">
+			<!-- wp:paragraph --><p>{{content}}</p><!-- /wp:paragraph -->
+			</div></div>
+			<!-- /wp:woocommerce/accordion-panel --></div>
+			<!-- /wp:woocommerce/accordion-item -->'
+		)[0];
+
+		foreach ( $template['innerBlocks'] as &$block ) {
+			if ( 'woocommerce/accordion-header' === $block['blockName'] ) {
+				$block['innerContent'] = array_map(
+					function ( $inner_content ) use ( $title ) {
+						return str_replace( '{{title}}', $title, $inner_content );
+					},
+					$block['innerContent']
+				);
+			}
+			if ( 'woocommerce/accordion-panel' === $block['blockName'] ) {
+				$block['innerBlocks']  = parse_blocks( $content );
+				$openning_tag          = reset( $block['innerContent'] );
+				$closing_tag           = end( $block['innerContent'] );
+				$block['innerContent'] = array_merge(
+					array( $openning_tag ),
+					array_fill( 0, count( $block['innerBlocks'] ), null ),
+					array( $closing_tag )
+				);
+			}
+		}
+
path: plugins/woocommerce/src/Blocks/BlockTypes/BlockifiedProductDetails.php
user: login: gigitux
body: Is there a particual reason to run all this logic? Can we pass the `title` and `content` in the template and parse it? 
created_at: 2025-05-14T10:16:03Z
author_association: CONTRIBUTOR
diff_hunk: @@ -35,69 +35,236 @@ protected function get_block_type_style() {
 	 * @return string Rendered block output.
 	 */
 	protected function render( $attributes, $content, $block ) {
-		return $this->hide_empty_accordion_items( $content, $block );
+		$parsed_block = $block->parsed_block;
+		$parsed_block = $this->hide_empty_accordion_items( $parsed_block, $block->context );
+		$parsed_block = $this->inject_compatible_tabs( $parsed_block );
+
+		$inner_content = array_reduce(
+			$parsed_block['innerBlocks'],
+			function ( $carry, $parsed_inner_block ) use ( $block ) {
+				$carry .= ( new \WP_Block( $parsed_inner_block, $block->context ) )->render();
+				return $carry;
+			},
+			''
+		);
+
+		return sprintf(
+			'<div %1$s>%2$s</div>',
+			get_block_wrapper_attributes(),
+			$inner_content
+		);
 	}
 
 	/**
-	 * Hide empty accordion items.
+	 * Inject compatible tabs.
 	 *
-	 * @param string   $content Block content.
-	 * @param WP_Block $block Block instance.
+	 * @param array $parsed_block Parsed block.
 	 *
-	 * @return string Rendered block output.
+	 * @return array Parsed block.
 	 */
-	private function hide_empty_accordion_items( $content, $block ) {
-		$accordion_items = $this->find_accordion_items( $block->parsed_block );
-
-		if ( ! $accordion_items ) {
-			return $content;
+	private function inject_compatible_tabs( $parsed_block ) {
+		if ( ! $this->has_accordion( $parsed_block ) ) {
+			return $parsed_block;
 		}
 
-		$accordion_items_visibility = array_map(
-			function ( $item ) use ( $block ) {
-				$content_block          = end( $item['innerBlocks'] );
-				$rendered_content_block = ( new WP_Block( $content_block, $block->context ) )->render();
-				$p                      = new WP_HTML_Tag_Processor( $rendered_content_block );
-
-				return $p->next_tag( 'img' ) ||
-					$p->next_tag( 'iframe' ) ||
-					$p->next_tag( 'video' ) ||
-					$p->next_tag( 'meter' ) ||
-					! empty( wp_strip_all_tags( $rendered_content_block, true ) );
-			},
-			$accordion_items
+		/**
+		 * Filter the product tabs in the product details block.
+		 *
+		 * @since 3.3.0
+		 * @param array $tabs Array of product tabs.
+		 */
+		$product_tabs = apply_filters(
+			'woocommerce_product_tabs',
+			array()
+		);
+
+		$default_tabs_callbacks = array(
+			'woocommerce_product_description_tab',
+			'woocommerce_product_additional_information_tab',
+			'comments_template',
+		);
+
+		$product_tabs = array_filter(
+			$product_tabs,
+			function ( $tab ) use ( $default_tabs_callbacks ) {
+				return ! in_array( $tab['callback'], $default_tabs_callbacks, true );
+			}
 		);
 
-		$p = new WP_HTML_Tag_Processor( $content );
+		usort(
+			$product_tabs,
+			function ( $a, $b ) {
+				return $a['priority'] <=> $b['priority'];
+			}
+		);
+
+		$accordion_blocks = array();
+
+		foreach ( $product_tabs as $key => $tab ) {
+			ob_start();
+			call_user_func( $tab['callback'], $key, $tab );
+			$tab_content        = ob_get_clean();
+			$accordion_blocks[] = $this->create_accordion_item_block(
+				$tab['title'],
+				'<!-- wp:html -->' . $tab_content . '<!-- /wp:html -->'
+			);
+		}
+
+		return $this->inject_parsed_accordion_blocks( $parsed_block, $accordion_blocks );
+	}
+
+	/**
+	 * Create an accordion item block.
+	 *
+	 * @param string $title Title of the accordion item.
+	 * @param string $content Content of the accordion item as block markup.
+	 *
+	 * @return array Accordion item.
+	 */
+	private function create_accordion_item_block( $title, $content ) {
+		$template = parse_blocks(
+			'<!-- wp:woocommerce/accordion-item -->
+			<div class="wp-block-woocommerce-accordion-item"><!-- wp:woocommerce/accordion-header -->
+			<h3 class="wp-block-woocommerce-accordion-header accordion-item__heading"><button class="accordion-item__toggle"><span>{{title}}</span><span class="accordion-item__toggle-icon has-icon-plus" style="width:1.2em;height:1.2em"><svg width="1.2em" height="1.2em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"><path d="M11 12.5V17.5H12.5V12.5H17.5V11H12.5V6H11V11H6V12.5H11Z" fill="currentColor"></path></svg></span></button></h3>
+			<!-- /wp:woocommerce/accordion-header -->
+
+			<!-- wp:woocommerce/accordion-panel -->
+			<div class="wp-block-woocommerce-accordion-panel"><div class="accordion-content__wrapper">
+			<!-- wp:paragraph --><p>{{content}}</p><!-- /wp:paragraph -->
+			</div></div>
+			<!-- /wp:woocommerce/accordion-panel --></div>
+			<!-- /wp:woocommerce/accordion-item -->'
+		)[0];
+
+		foreach ( $template['innerBlocks'] as &$block ) {
+			if ( 'woocommerce/accordion-header' === $block['blockName'] ) {
+				$block['innerContent'] = array_map(
+					function ( $inner_content ) use ( $title ) {
+						return str_replace( '{{title}}', $title, $inner_content );
+					},
+					$block['innerContent']
+				);
+			}
+			if ( 'woocommerce/accordion-panel' === $block['blockName'] ) {
+				$block['innerBlocks']  = parse_blocks( $content );
+				$openning_tag          = reset( $block['innerContent'] );
+				$closing_tag           = end( $block['innerContent'] );
+				$block['innerContent'] = array_merge(
+					array( $openning_tag ),
+					array_fill( 0, count( $block['innerBlocks'] ), null ),
+					array( $closing_tag )
+				);
+			}
+		}
+
path: plugins/woocommerce/src/Blocks/BlockTypes/BlockifiedProductDetails.php
user: login: dinhtungdu
body: Ah you're right! It was the result of 770a380e3f32e32d4caf76ff7ccb27112fcfc429. I will revert it for now. But be aware that this will change when [Bernie PR](https://github.com/woocommerce/woocommerce/pull/57893#issuecomment-2877197583) is merged.
created_at: 2025-05-15T01:41:14Z
author_association: MEMBER
diff_hunk: @@ -35,69 +35,236 @@ protected function get_block_type_style() {
 	 * @return string Rendered block output.
 	 */
 	protected function render( $attributes, $content, $block ) {
-		return $this->hide_empty_accordion_items( $content, $block );
+		$parsed_block = $block->parsed_block;
+		$parsed_block = $this->hide_empty_accordion_items( $parsed_block, $block->context );
+		$parsed_block = $this->inject_compatible_tabs( $parsed_block );
+
+		$inner_content = array_reduce(
+			$parsed_block['innerBlocks'],
+			function ( $carry, $parsed_inner_block ) use ( $block ) {
+				$carry .= ( new \WP_Block( $parsed_inner_block, $block->context ) )->render();
+				return $carry;
+			},
+			''
+		);
+
+		return sprintf(
+			'<div %1$s>%2$s</div>',
+			get_block_wrapper_attributes(),
+			$inner_content
+		);
 	}
 
 	/**
-	 * Hide empty accordion items.
+	 * Inject compatible tabs.
 	 *
-	 * @param string   $content Block content.
-	 * @param WP_Block $block Block instance.
+	 * @param array $parsed_block Parsed block.
 	 *
-	 * @return string Rendered block output.
+	 * @return array Parsed block.
 	 */
-	private function hide_empty_accordion_items( $content, $block ) {
-		$accordion_items = $this->find_accordion_items( $block->parsed_block );
-
-		if ( ! $accordion_items ) {
-			return $content;
+	private function inject_compatible_tabs( $parsed_block ) {
+		if ( ! $this->has_accordion( $parsed_block ) ) {
+			return $parsed_block;
 		}
 
-		$accordion_items_visibility = array_map(
-			function ( $item ) use ( $block ) {
-				$content_block          = end( $item['innerBlocks'] );
-				$rendered_content_block = ( new WP_Block( $content_block, $block->context ) )->render();
-				$p                      = new WP_HTML_Tag_Processor( $rendered_content_block );
-
-				return $p->next_tag( 'img' ) ||
-					$p->next_tag( 'iframe' ) ||
-					$p->next_tag( 'video' ) ||
-					$p->next_tag( 'meter' ) ||
-					! empty( wp_strip_all_tags( $rendered_content_block, true ) );
-			},
-			$accordion_items
+		/**
+		 * Filter the product tabs in the product details block.
+		 *
+		 * @since 3.3.0
+		 * @param array $tabs Array of product tabs.
+		 */
+		$product_tabs = apply_filters(
+			'woocommerce_product_tabs',
+			array()
+		);
+
+		$default_tabs_callbacks = array(
+			'woocommerce_product_description_tab',
+			'woocommerce_product_additional_information_tab',
+			'comments_template',
+		);
+
+		$product_tabs = array_filter(
+			$product_tabs,
+			function ( $tab ) use ( $default_tabs_callbacks ) {
+				return ! in_array( $tab['callback'], $default_tabs_callbacks, true );
+			}
 		);
 
-		$p = new WP_HTML_Tag_Processor( $content );
+		usort(
+			$product_tabs,
+			function ( $a, $b ) {
+				return $a['priority'] <=> $b['priority'];
+			}
+		);
+
+		$accordion_blocks = array();
+
+		foreach ( $product_tabs as $key => $tab ) {
+			ob_start();
+			call_user_func( $tab['callback'], $key, $tab );
+			$tab_content        = ob_get_clean();
+			$accordion_blocks[] = $this->create_accordion_item_block(
+				$tab['title'],
+				'<!-- wp:html -->' . $tab_content . '<!-- /wp:html -->'
+			);
+		}
+
+		return $this->inject_parsed_accordion_blocks( $parsed_block, $accordion_blocks );
+	}
+
+	/**
+	 * Create an accordion item block.
+	 *
+	 * @param string $title Title of the accordion item.
+	 * @param string $content Content of the accordion item as block markup.
+	 *
+	 * @return array Accordion item.
+	 */
+	private function create_accordion_item_block( $title, $content ) {
+		$template = parse_blocks(
+			'<!-- wp:woocommerce/accordion-item -->
+			<div class="wp-block-woocommerce-accordion-item"><!-- wp:woocommerce/accordion-header -->
+			<h3 class="wp-block-woocommerce-accordion-header accordion-item__heading"><button class="accordion-item__toggle"><span>{{title}}</span><span class="accordion-item__toggle-icon has-icon-plus" style="width:1.2em;height:1.2em"><svg width="1.2em" height="1.2em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"><path d="M11 12.5V17.5H12.5V12.5H17.5V11H12.5V6H11V11H6V12.5H11Z" fill="currentColor"></path></svg></span></button></h3>
+			<!-- /wp:woocommerce/accordion-header -->
+
+			<!-- wp:woocommerce/accordion-panel -->
+			<div class="wp-block-woocommerce-accordion-panel"><div class="accordion-content__wrapper">
+			<!-- wp:paragraph --><p>{{content}}</p><!-- /wp:paragraph -->
+			</div></div>
+			<!-- /wp:woocommerce/accordion-panel --></div>
+			<!-- /wp:woocommerce/accordion-item -->'
+		)[0];
+
+		foreach ( $template['innerBlocks'] as &$block ) {
+			if ( 'woocommerce/accordion-header' === $block['blockName'] ) {
+				$block['innerContent'] = array_map(
+					function ( $inner_content ) use ( $title ) {
+						return str_replace( '{{title}}', $title, $inner_content );
+					},
+					$block['innerContent']
+				);
+			}
+			if ( 'woocommerce/accordion-panel' === $block['blockName'] ) {
+				$block['innerBlocks']  = parse_blocks( $content );
+				$openning_tag          = reset( $block['innerContent'] );
+				$closing_tag           = end( $block['innerContent'] );
+				$block['innerContent'] = array_merge(
+					array( $openning_tag ),
+					array_fill( 0, count( $block['innerBlocks'] ), null ),
+					array( $closing_tag )
+				);
+			}
+		}
+
+		return $template;
+	}
+
+	/**
+	 * Inject parsed accordion blocks.
+	 *
+	 * @param array $parsed_block Parsed block.
+	 * @param array $accordion_blocks Accordion blocks.
+	 *
+	 * @return array Parsed block.
+	 */
+	private function inject_parsed_accordion_blocks( $parsed_block, $accordion_blocks ) {
+		if ( 'woocommerce/accordion-group' === $parsed_block['blockName'] ) {
+			$parsed_block['innerBlocks']  = array_merge( $parsed_block['innerBlocks'], $accordion_blocks );
+			$parsed_block['innerBlocks']  = array_values( array_filter( $parsed_block['innerBlocks'] ) );
+			$openning_tag                 = reset( $parsed_block['innerContent'] );
+			$closing_tag                  = end( $parsed_block['innerContent'] );
+			$parsed_block['innerContent'] = array_merge(
+				array( $openning_tag ),
+				array_fill( 0, count( $parsed_block['innerBlocks'] ), null ),
+				array( $closing_tag )
+			);
+			return $parsed_block;
+		}
+
+		foreach ( $parsed_block['innerBlocks'] as $key => $inner_block ) {
+			$parsed_block['innerBlocks'][ $key ] = $this->inject_parsed_accordion_blocks( $inner_block, $accordion_blocks );
+		}
+
+		return $parsed_block;
+	}
+
+	/**
+	 * Hide empty accordion items.
+	 *
+	 * @param array $parsed_block Parsed block.
+	 * @param array $context Context.
+	 *
+	 * @return array Parsed block.
+	 */
+	private function hide_empty_accordion_items( $parsed_block, $context ) {
+		if ( ! $this->has_accordion( $parsed_block ) ) {
+			return $parsed_block;
+		}
 
-		$counter = 0;
-		while ( $p->next_tag( array( 'class_name' => 'wp-block-woocommerce-accordion-item' ) ) ) {
-			if ( ! $accordion_items_visibility[ $counter ] ) {
-				$p->set_attribute( 'style', 'display:none;' );
-				$p->set_attribute( 'hidden', true );
+		if ( 'woocommerce/accordion-group' === $parsed_block['blockName'] ) {
+			foreach ( $parsed_block['innerBlocks'] as $key => $inner_block ) {
+				$parsed_block['innerBlocks'][ $key ] = $this->mark_accordion_item_hidden( $inner_block, $context );
 			}
-			++$counter;
+			$parsed_block['innerBlocks']  = array_values( array_filter( $parsed_block['innerBlocks'] ) );
+			$openning_tag                 = reset( $parsed_block['innerContent'] );
path: plugins/woocommerce/src/Blocks/BlockTypes/BlockifiedProductDetails.php
user: login: dinhtungdu
body: Thanks! I fixed in [`fb66ee7` (#57973)](https://github.com/woocommerce/woocommerce/pull/57973/commits/fb66ee7e8daa0e73941b9beab3733dfd3acd5538).
created_at: 2025-05-15T02:13:11Z
author_association: MEMBER

PR comments:
user: login: github-actions[bot]
created_at: 2025-05-14T02:37:57Z
body: ## Testing Guidelines
Hi @gigitux @kmanijak ,

Apart from reviewing the code changes, please make sure to **review the testing instructions** ([Guide](https://github.com/woocommerce/woocommerce/wiki/Writing-high-quality-testing-instructions)) and verify that relevant tests (E2E, Unit, Integration, etc.) have been added or updated as needed.

**Reminder:** PR reviewers are required to document testing performed. This includes:
- 🖼️ **Screenshots or screen recordings**.
- 📝 **List of functionality tested / steps followed**.
- 🌐 **Site details** (environment attributes such as hosting type, plugins, theme, store size, store age, and relevant settings).
- 🔍 **Any analysis performed**, such as assessing potential impacts on environment attributes and other plugins, conducting performance profiling, or using LLM/AI-based analysis.

⚠️ Within the testing details you provide, please ensure that no sensitive information (such as API keys, passwords, user data, etc.) is included in this public issue.
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-05-14T02:44:46Z
body: 
## Test using WordPress Playground
The changes in this pull request can be previewed and tested using a [WordPress Playground](https://developer.wordpress.org/playground/) instance.
[WordPress Playground](https://developer.wordpress.org/playground/) is an experimental project that creates a full WordPress instance entirely within the browser.

[Test this pull request with WordPress Playground](https://wordpress-playground.atomicsites.blog/#{"landingPage":"/wp-admin/admin.php?page=wc-admin","preferredVersions":{"php":"8.0","wp":"latest"},"phpExtensionBundles":["kitchen-sink"],"features":{"networking":true},"steps":[{"step":"installPlugin","pluginZipFile":{"resource":"url","url":"https://playground.wordpress.net/plugin-proxy.php?org=woocommerce&repo=woocommerce&workflow=Build%20Live%20Branch&artifact=plugins-15035059487&pr=57973"},"options":{"activate":true}},{"step":"installPlugin","pluginZipFile":{"resource":"url","url":"https://github-proxy.com/https://github.com/woocommerce/woocommerce/releases/download/wc-beta-tester-2.3.1/woocommerce-beta-tester.zip"},"options":{"activate":true}},{"step":"setSiteOptions","options":{"woocommerce_onboarding_profile":{"skipped":true}}},{"step":"login","username":"admin","password":"password"}],"plugins":[]}).

Note that this URL is valid for 30 days from when this comment was last updated. You can update it by closing/reopening the PR or pushing a new commit.

author_association: CONTRIBUTOR
user: login: dinhtungdu
created_at: 2025-05-14T09:51:51Z
body: > Can you tell me if it's more of an experiment still or this is in state for final review?

@kmanijak after [9ecc027](https://github.com/woocommerce/woocommerce/pull/57973/commits/9ecc0274884ab568b40fb7c23db5fc72dfa1dda9), this PR is now in the final form.
author_association: MEMBER
user: login: dinhtungdu
created_at: 2025-05-15T02:19:15Z
body: Thanks @gigitux and @kmanijak for your reviews!

@gigitux I copied the tests from your PR in [b97f4c3](https://github.com/woocommerce/woocommerce/pull/57973/commits/b97f4c325e9afe2084c99ec5bc8fbf7b523d49e4). I also added the hook to disable the compatibility layer in [fb66ee7](https://github.com/woocommerce/woocommerce/pull/57973/commits/fb66ee7e8daa0e73941b9beab3733dfd3acd5538), we can later update that hook to accept a block or template argument so developers can selectively disable the layer.

This is ready to review again, please take another look.
author_association: MEMBER