Add 'Show tab title' attribute to the Product Details block (#50884)
* Add 'Show tab title' attribute to the Product Details block * Add tests * Add changelog file * Linting * Use editor.selectBlocks() instead of block.click()
This commit is contained in:
parent
f2941d76e5
commit
1e650d06a9
|
@ -5,6 +5,12 @@
|
||||||
"title": "Product Details",
|
"title": "Product Details",
|
||||||
"description": "Display a product's description, attributes, and reviews.",
|
"description": "Display a product's description, attributes, and reviews.",
|
||||||
"category": "woocommerce-product-elements",
|
"category": "woocommerce-product-elements",
|
||||||
|
"attributes": {
|
||||||
|
"hideTabTitle": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false
|
||||||
|
}
|
||||||
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"WooCommerce"
|
"WooCommerce"
|
||||||
],
|
],
|
||||||
|
|
|
@ -8,7 +8,7 @@ interface SingleProductTab {
|
||||||
id: string;
|
id: string;
|
||||||
title: string;
|
title: string;
|
||||||
active: boolean;
|
active: boolean;
|
||||||
content: string | undefined;
|
content: React.JSX.Element | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ProductTabTitle = ( {
|
const ProductTabTitle = ( {
|
||||||
|
@ -46,15 +46,28 @@ const ProductTabContent = ( {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const SingleProductDetails = () => {
|
export const SingleProductDetails = ( {
|
||||||
|
hideTabTitle,
|
||||||
|
}: {
|
||||||
|
hideTabTitle: boolean;
|
||||||
|
} ) => {
|
||||||
const productTabs = [
|
const productTabs = [
|
||||||
{
|
{
|
||||||
id: 'description',
|
id: 'description',
|
||||||
title: 'Description',
|
title: 'Description',
|
||||||
active: true,
|
active: true,
|
||||||
content: __(
|
content: (
|
||||||
'This block lists description, attributes and reviews for a single product.',
|
<>
|
||||||
'woocommerce'
|
{ ! hideTabTitle && (
|
||||||
|
<h2>{ __( 'Description', 'woocommerce' ) }</h2>
|
||||||
|
) }
|
||||||
|
<p>
|
||||||
|
{ __(
|
||||||
|
'This block lists description, attributes and reviews for a single product.',
|
||||||
|
'woocommerce'
|
||||||
|
) }
|
||||||
|
</p>
|
||||||
|
</>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
/**
|
/**
|
||||||
* External dependencies
|
* External dependencies
|
||||||
*/
|
*/
|
||||||
import { useBlockProps } from '@wordpress/block-editor';
|
import { InspectorControls, useBlockProps } from '@wordpress/block-editor';
|
||||||
import { Disabled } from '@wordpress/components';
|
import { Disabled, PanelBody, ToggleControl } from '@wordpress/components';
|
||||||
import type { BlockEditProps } from '@wordpress/blocks';
|
import type { BlockEditProps } from '@wordpress/blocks';
|
||||||
|
import { __ } from '@wordpress/i18n';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal dependencies
|
* Internal dependencies
|
||||||
|
@ -12,8 +13,11 @@ import Block from './block';
|
||||||
import { Attributes } from './types';
|
import { Attributes } from './types';
|
||||||
import './editor.scss';
|
import './editor.scss';
|
||||||
|
|
||||||
const Edit = ( { attributes }: BlockEditProps< Attributes > ) => {
|
const Edit = ( {
|
||||||
const { className } = attributes;
|
attributes,
|
||||||
|
setAttributes,
|
||||||
|
}: BlockEditProps< Attributes > ) => {
|
||||||
|
const { className, hideTabTitle } = attributes;
|
||||||
const blockProps = useBlockProps( {
|
const blockProps = useBlockProps( {
|
||||||
className,
|
className,
|
||||||
} );
|
} );
|
||||||
|
@ -21,8 +25,24 @@ const Edit = ( { attributes }: BlockEditProps< Attributes > ) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div { ...blockProps }>
|
<div { ...blockProps }>
|
||||||
|
<InspectorControls key="inspector">
|
||||||
|
<PanelBody title={ __( 'Settings', 'woocommerce' ) }>
|
||||||
|
<ToggleControl
|
||||||
|
label={ __(
|
||||||
|
'Show tab title in content',
|
||||||
|
'woocommerce'
|
||||||
|
) }
|
||||||
|
checked={ ! hideTabTitle }
|
||||||
|
onChange={ () =>
|
||||||
|
setAttributes( {
|
||||||
|
hideTabTitle: ! hideTabTitle,
|
||||||
|
} )
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</PanelBody>
|
||||||
|
</InspectorControls>
|
||||||
<Disabled>
|
<Disabled>
|
||||||
<Block />
|
<Block hideTabTitle={ hideTabTitle } />
|
||||||
</Disabled>
|
</Disabled>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
export interface Attributes {
|
export interface Attributes {
|
||||||
className?: string;
|
className?: string;
|
||||||
|
hideTabTitle?: boolean;
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,4 +55,56 @@ test.describe( `${ blockData.slug } Block`, () => {
|
||||||
/This block lists description, attributes and reviews for a single product./
|
/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();
|
||||||
|
} );
|
||||||
} );
|
} );
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
Significance: minor
|
||||||
|
Type: enhancement
|
||||||
|
|
||||||
|
Add 'Show tab title' attribute to the Product Details block
|
|
@ -1,6 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Automattic\WooCommerce\Blocks\BlockTypes;
|
namespace Automattic\WooCommerce\Blocks\BlockTypes;
|
||||||
|
|
||||||
|
use WP_HTML_Tag_Processor;
|
||||||
use Automattic\WooCommerce\Blocks\Utils\StyleAttributesUtils;
|
use Automattic\WooCommerce\Blocks\Utils\StyleAttributesUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -50,8 +51,31 @@ class ProductDetails extends AbstractBlock {
|
||||||
* @return string Rendered block output.
|
* @return string Rendered block output.
|
||||||
*/
|
*/
|
||||||
protected function render( $attributes, $content, $block ) {
|
protected function render( $attributes, $content, $block ) {
|
||||||
|
$hide_tab_title = isset( $attributes['hideTabTitle'] ) ? $attributes['hideTabTitle'] : false;
|
||||||
|
|
||||||
|
if ( $hide_tab_title ) {
|
||||||
|
add_filter( 'woocommerce_product_description_heading', '__return_empty_string' );
|
||||||
|
add_filter( 'woocommerce_product_additional_information_heading', '__return_empty_string' );
|
||||||
|
add_filter( 'woocommerce_reviews_title', '__return_empty_string' );
|
||||||
|
}
|
||||||
|
|
||||||
$tabs = $this->render_tabs();
|
$tabs = $this->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'] ?? '';
|
$classname = $attributes['className'] ?? '';
|
||||||
|
|
||||||
$classes_and_styles = StyleAttributesUtils::get_classes_and_styles_by_attributes( $attributes );
|
$classes_and_styles = StyleAttributesUtils::get_classes_and_styles_by_attributes( $attributes );
|
||||||
|
|
Loading…
Reference in New Issue