diff --git a/plugins/woocommerce-blocks/assets/js/atomic/blocks/product-elements/product-details/block.json b/plugins/woocommerce-blocks/assets/js/atomic/blocks/product-elements/product-details/block.json
index 6e8df5f272d..633c831d1c6 100644
--- a/plugins/woocommerce-blocks/assets/js/atomic/blocks/product-elements/product-details/block.json
+++ b/plugins/woocommerce-blocks/assets/js/atomic/blocks/product-elements/product-details/block.json
@@ -5,6 +5,12 @@
"title": "Product Details",
"description": "Display a product's description, attributes, and reviews.",
"category": "woocommerce-product-elements",
+ "attributes": {
+ "hideTabTitle": {
+ "type": "boolean",
+ "default": false
+ }
+ },
"keywords": [
"WooCommerce"
],
diff --git a/plugins/woocommerce-blocks/assets/js/atomic/blocks/product-elements/product-details/block.tsx b/plugins/woocommerce-blocks/assets/js/atomic/blocks/product-elements/product-details/block.tsx
index a011fb84da8..169f7c7cab1 100644
--- a/plugins/woocommerce-blocks/assets/js/atomic/blocks/product-elements/product-details/block.tsx
+++ b/plugins/woocommerce-blocks/assets/js/atomic/blocks/product-elements/product-details/block.tsx
@@ -8,7 +8,7 @@ interface SingleProductTab {
id: string;
title: string;
active: boolean;
- content: string | undefined;
+ content: React.JSX.Element | undefined;
}
const ProductTabTitle = ( {
@@ -46,15 +46,28 @@ const ProductTabContent = ( {
);
};
-export const SingleProductDetails = () => {
+export const SingleProductDetails = ( {
+ hideTabTitle,
+}: {
+ hideTabTitle: boolean;
+} ) => {
const productTabs = [
{
id: 'description',
title: 'Description',
active: true,
- content: __(
- 'This block lists description, attributes and reviews for a single product.',
- 'woocommerce'
+ content: (
+ <>
+ { ! hideTabTitle && (
+
{ __( 'Description', 'woocommerce' ) }
+ ) }
+
+ { __(
+ 'This block lists description, attributes and reviews for a single product.',
+ 'woocommerce'
+ ) }
+
+ >
),
},
{
diff --git a/plugins/woocommerce-blocks/assets/js/atomic/blocks/product-elements/product-details/edit.tsx b/plugins/woocommerce-blocks/assets/js/atomic/blocks/product-elements/product-details/edit.tsx
index 471f9f7e30b..d4d652c3ee2 100644
--- a/plugins/woocommerce-blocks/assets/js/atomic/blocks/product-elements/product-details/edit.tsx
+++ b/plugins/woocommerce-blocks/assets/js/atomic/blocks/product-elements/product-details/edit.tsx
@@ -1,9 +1,10 @@
/**
* External dependencies
*/
-import { useBlockProps } from '@wordpress/block-editor';
-import { Disabled } from '@wordpress/components';
+import { InspectorControls, useBlockProps } from '@wordpress/block-editor';
+import { Disabled, PanelBody, ToggleControl } from '@wordpress/components';
import type { BlockEditProps } from '@wordpress/blocks';
+import { __ } from '@wordpress/i18n';
/**
* Internal dependencies
@@ -12,8 +13,11 @@ import Block from './block';
import { Attributes } from './types';
import './editor.scss';
-const Edit = ( { attributes }: BlockEditProps< Attributes > ) => {
- const { className } = attributes;
+const Edit = ( {
+ attributes,
+ setAttributes,
+}: BlockEditProps< Attributes > ) => {
+ const { className, hideTabTitle } = attributes;
const blockProps = useBlockProps( {
className,
} );
@@ -21,8 +25,24 @@ const Edit = ( { attributes }: BlockEditProps< Attributes > ) => {
return (
<>
+
+
+
+ setAttributes( {
+ hideTabTitle: ! hideTabTitle,
+ } )
+ }
+ />
+
+
-
+
>
diff --git a/plugins/woocommerce-blocks/assets/js/atomic/blocks/product-elements/product-details/types.ts b/plugins/woocommerce-blocks/assets/js/atomic/blocks/product-elements/product-details/types.ts
index aa9b37b316a..36a5d5b5d58 100644
--- a/plugins/woocommerce-blocks/assets/js/atomic/blocks/product-elements/product-details/types.ts
+++ b/plugins/woocommerce-blocks/assets/js/atomic/blocks/product-elements/product-details/types.ts
@@ -1,3 +1,4 @@
export interface Attributes {
className?: string;
+ hideTabTitle?: boolean;
}
diff --git a/plugins/woocommerce-blocks/tests/e2e/tests/single-product-details/single-product-details.block_theme.spec.ts b/plugins/woocommerce-blocks/tests/e2e/tests/single-product-details/single-product-details.block_theme.spec.ts
index 967ddf62d00..9e45c19be36 100644
--- a/plugins/woocommerce-blocks/tests/e2e/tests/single-product-details/single-product-details.block_theme.spec.ts
+++ b/plugins/woocommerce-blocks/tests/e2e/tests/single-product-details/single-product-details.block_theme.spec.ts
@@ -55,4 +55,56 @@ test.describe( `${ blockData.slug } Block`, () => {
/This block lists description, attributes and reviews for a single product./
);
} );
+
+ test( 'block hides tab title in content when toggle is off', async ( {
+ admin,
+ requestUtils,
+ editor,
+ page,
+ frontendUtils,
+ } ) => {
+ const template = await requestUtils.createTemplate( 'wp_template', {
+ slug: 'single-product-v-neck-t-shirt',
+ title: 'Product Details Test',
+ content: '',
+ } );
+
+ await admin.visitSiteEditor( {
+ postId: template.id,
+ postType: 'wp_template',
+ canvas: 'edit',
+ } );
+
+ await editor.insertBlock( {
+ name: blockData.slug,
+ } );
+
+ const block = await editor.getBlockByName( blockData.slug );
+ await editor.selectBlocks( block );
+
+ // Verify the "Description" h2 heading is visible by default.
+ await expect(
+ editor.canvas.locator( 'h2:has-text("Description")' )
+ ).toBeVisible();
+
+ await editor.openDocumentSettingsSidebar();
+ await page.getByText( 'Show tab title in content' ).click();
+
+ // Verify the "Description" h2 heading has been hidden from the canvas.
+ await expect(
+ editor.canvas.locator( 'h2:has-text("Description")' )
+ ).toBeHidden();
+
+ await editor.saveSiteEditorEntities( {
+ isOnlyCurrentEntityDirty: true,
+ } );
+
+ await frontendUtils.goToShop();
+ await page.getByText( 'V-Neck T-Shirt' ).click();
+
+ // Verify the "Description" h2 heading is not in the page.
+ await expect(
+ page.locator( 'h2:has-text("Description")' )
+ ).toBeHidden();
+ } );
} );
diff --git a/plugins/woocommerce/changelog/add-47895-show-tab-title-attribute-product-details b/plugins/woocommerce/changelog/add-47895-show-tab-title-attribute-product-details
new file mode 100644
index 00000000000..9b974a1f1cf
--- /dev/null
+++ b/plugins/woocommerce/changelog/add-47895-show-tab-title-attribute-product-details
@@ -0,0 +1,4 @@
+Significance: minor
+Type: enhancement
+
+Add 'Show tab title' attribute to the Product Details block
diff --git a/plugins/woocommerce/src/Blocks/BlockTypes/ProductDetails.php b/plugins/woocommerce/src/Blocks/BlockTypes/ProductDetails.php
index c512966d6ad..907d198dde9 100644
--- a/plugins/woocommerce/src/Blocks/BlockTypes/ProductDetails.php
+++ b/plugins/woocommerce/src/Blocks/BlockTypes/ProductDetails.php
@@ -1,6 +1,7 @@
render_tabs();
+ if ( $hide_tab_title ) {
+ remove_filter( 'woocommerce_product_description_heading', '__return_empty_string' );
+ remove_filter( 'woocommerce_product_additional_information_heading', '__return_empty_string' );
+ remove_filter( 'woocommerce_reviews_title', '__return_empty_string' );
+
+ // Remove the first `h2` of every `.wc-tab`. This is required for the Reviews tabs when there are no reviews and for plugin tabs.
+ $tabs_html = new WP_HTML_Tag_Processor( $tabs );
+ while ( $tabs_html->next_tag( array( 'class_name' => 'wc-tab' ) ) ) {
+ if ( $tabs_html->next_tag( 'h2' ) ) {
+ $tabs_html->set_attribute( 'hidden', 'true' );
+ }
+ }
+ $tabs = $tabs_html->get_updated_html();
+ }
+
$classname = $attributes['className'] ?? '';
$classes_and_styles = StyleAttributesUtils::get_classes_and_styles_by_attributes( $attributes );