* Add the initial basis for the Add to Cart button

* Trigger the single product add to cart action for each product type.

* Rename the block from add-to-cart-button to add-to-cart-form

* Update to use the cart icon.

* Implement the skeleton for the editor preview.

* Update styles and add Notice for the display in the Editor.

* Update CSS.

* Add base tests for the new Add to Cart Form component.

* Update the button CSS.

* Update styles for the cart form.

* update td style.

* Update divs and CSS.

* Use conventional input instead of the experimental InputControl

* Implement the new design and copy provided for the editor.

* Make the notice compatible with dark themes.

* Some additional CSS tweaks

* adjust the padding for the input

* Update the icon for the block to match the core icon button
This commit is contained in:
Patricia Hillebrandt 2023-02-16 11:43:37 +01:00 committed by GitHub
parent 3b04dbb01f
commit 9e0c20d43e
9 changed files with 254 additions and 0 deletions

View File

@ -0,0 +1,11 @@
{
"name": "woocommerce/add-to-cart-form",
"version": "1.0.0",
"title": "Add to Cart form",
"description": "Display a button so the customer can add a product to their cart. Options will also be displayed depending on product type. e.g. quantity, variation.",
"category": "woocommerce",
"keywords": [ "WooCommerce" ],
"textdomain": "woo-gutenberg-products-block",
"apiVersion": 2,
"$schema": "https://schemas.wp.org/trunk/block.json"
}

View File

@ -0,0 +1,51 @@
/**
* External dependencies
*/
import { useBlockProps } from '@wordpress/block-editor';
import { __ } from '@wordpress/i18n';
import { Button, Disabled, Notice } from '@wordpress/components';
/**
* Internal dependencies
*/
import './editor.scss';
export interface Attributes {
className?: string;
}
const Edit = () => {
const blockProps = useBlockProps( {
className: 'woocommerce wc-block-add-to-cart-form',
} );
return (
<div { ...blockProps }>
<Disabled>
<Notice
className={ 'wc-block-add-to-cart-form__notice' }
status={ 'warning' }
isDismissible={ false }
>
<p>
{ __(
'Customers will see product add-to-cart options displayed here, dependent on the product type.',
'woo-gutenberg-products-block'
) }
</p>
</Notice>
<input
type={ 'number' }
value={ '1' }
className={ 'wc-block-add-to-cart-form__quantity' }
/>
<Button
variant={ 'primary' }
className={ 'wc-block-add-to-cart-form__button' }
>
{ __( 'Add to cart', 'woo-gutenberg-products-block' ) }
</Button>
</Disabled>
</div>
);
};
export default Edit;

View File

@ -0,0 +1,27 @@
.wc-block-add-to-cart-form {
display: flex;
flex-direction: row;
}
.wc-block-add-to-cart-form__notice {
margin: 10px 0;
color: $black;
max-width: 60%;
}
input.wc-block-add-to-cart-form__quantity {
width: 35px;
float: left;
padding: 10px 6px 10px 12px;
margin-right: 10px;
height: 15px;
}
input[type="number"]::-webkit-inner-spin-button {
opacity: 1;
}
.wc-block-add-to-cart-form__button {
float: left;
padding: 20px 30px;
border-radius: 0;
}

View File

@ -0,0 +1,29 @@
/**
* External dependencies
*/
import { registerBlockType } from '@wordpress/blocks';
import { Icon, button } from '@wordpress/icons';
/**
* Internal dependencies
*/
import metadata from './block.json';
import edit from './edit';
registerBlockType( metadata, {
icon: {
src: (
<Icon
icon={ button }
className="wc-block-editor-components-block-icon"
/>
),
},
attributes: {
...metadata.attributes,
},
edit,
save() {
return null;
},
} );

View File

@ -0,0 +1,7 @@
.woocommerce.wc-block-add-to-cart-form {
font-size: inherit;
}
.woocommerce .wc-block-add-to-cart-form .product .summary {
float: left;
}

View File

@ -13,6 +13,7 @@ const glob = require( 'glob' );
// property.
const blocks = {
'active-filters': {},
'add-to-cart-form': {},
'all-products': {
customDir: 'products/all-products',
},

View File

@ -0,0 +1,65 @@
<?php
namespace Automattic\WooCommerce\Blocks\BlockTypes;
use Automattic\WooCommerce\Blocks\Utils\StyleAttributesUtils;
/**
* CatalogSorting class.
*/
class AddToCartForm extends AbstractBlock {
/**
* Block name.
*
* @var string
*/
protected $block_name = 'add-to-cart-form';
/**
* Render the block.
*
* @param array $attributes Block attributes.
* @param string $content Block content.
* @param WP_Block $block Block instance.
*
* @return string | void Rendered block output.
*/
protected function render( $attributes, $content, $block ) {
ob_start();
while ( have_posts() ) {
the_post();
global $product;
/**
* Trigger the single product add to cart action for each product type.
*/
do_action( 'woocommerce_' . $product->get_type() . '_add_to_cart' );
}
$product = ob_get_clean();
if ( ! $product ) {
return;
}
$classname = $attributes['className'] ?? '';
$classes_and_styles = StyleAttributesUtils::get_classes_and_styles_by_attributes( $attributes );
return sprintf(
'<div class="woocommerce wc-block-add-to-cart-form %1$s %2$s" style="%3$s"><div class="product type-product"><div class="summary entry-summary">%4$s</div></div></div>',
esc_attr( $classes_and_styles['classes'] ),
esc_attr( $classname ),
esc_attr( $classes_and_styles['styles'] ),
$product
);
}
/**
* Get the frontend script handle for this block type.
*
* @param string $key Data to get, or default to everything.
*/
protected function get_block_type_script( $key = null ) {
return null;
}
}

View File

@ -165,6 +165,7 @@ final class BlockTypesController {
$block_types = [
'ActiveFilters',
'AddToCartForm',
'AllProducts',
'AllReviews',
'AttributeFilter',
@ -252,6 +253,7 @@ final class BlockTypesController {
$block_types = array_diff(
$block_types,
[
'AddToCartForm',
'Breadcrumbs',
'CatalogSorting',
'ClassicTemplate',

View File

@ -0,0 +1,61 @@
/**
* External dependencies
*/
import {
canvas,
createNewPost,
insertBlock,
switchUserToAdmin,
} from '@wordpress/e2e-test-utils';
import { searchForBlock } from '@wordpress/e2e-test-utils/build/inserter';
/**
* Internal dependencies
*/
import {
filterCurrentBlocks,
goToSiteEditor,
useTheme,
waitForCanvas,
} from '../../utils.js';
const block = {
name: 'Add to Cart form',
slug: 'woocommerce/add-to-cart-form',
class: '.wc-block-add-to-cart-form',
};
describe( `${ block.name } Block`, () => {
it( 'in can not be inserted in a post', async () => {
await switchUserToAdmin();
await createNewPost( {
postType: 'post',
title: block.name,
} );
await searchForBlock( block.name );
expect( page ).toMatch( 'No results found.' );
} );
describe( 'in FSE editor', () => {
useTheme( 'emptytheme' );
beforeEach( async () => {
await goToSiteEditor();
await waitForCanvas();
} );
it( 'can be inserted in FSE area', async () => {
await insertBlock( block.name );
await expect( canvas() ).toMatchElement( block.class );
} );
it( 'can be inserted more than once', async () => {
await insertBlock( block.name );
await insertBlock( block.name );
const foo = await filterCurrentBlocks(
( b ) => b.name === block.slug
);
expect( foo ).toHaveLength( 2 );
} );
} );
} );