Create the Add to Cart Form Block (https://github.com/woocommerce/woocommerce-blocks/pull/8284)
* 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:
parent
3b04dbb01f
commit
9e0c20d43e
|
@ -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"
|
||||
}
|
|
@ -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;
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
},
|
||||
} );
|
|
@ -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;
|
||||
}
|
|
@ -13,6 +13,7 @@ const glob = require( 'glob' );
|
|||
// property.
|
||||
const blocks = {
|
||||
'active-filters': {},
|
||||
'add-to-cart-form': {},
|
||||
'all-products': {
|
||||
customDir: 'products/all-products',
|
||||
},
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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',
|
||||
|
|
|
@ -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 );
|
||||
} );
|
||||
} );
|
||||
} );
|
Loading…
Reference in New Issue