Skip to content
This repository has been archived by the owner on Feb 23, 2024. It is now read-only.

Commit

Permalink
[Mini cart] Make the title customizable (#8905)
Browse files Browse the repository at this point in the history
* Create the counter block and the header pattern

* Change the pattern to an inner block

* Allow customizing item counter block

* Rename block

* Allow removing the items counter block

* Add padding controls

* Preload new blocks

* Add title block back from the inserter

* Move h2 tag to the parent title

* Align items at the bottom

* Unify styles

* Add title class in the editor

* Prevent removing title blocks

* Disallow unlocking and inserter

* Disallowing moving blocks
  • Loading branch information
albarin authored Apr 14, 2023
1 parent c81dbd1 commit 2300e1f
Show file tree
Hide file tree
Showing 24 changed files with 444 additions and 42 deletions.
6 changes: 5 additions & 1 deletion assets/js/blocks/mini-cart/mini-cart-contents/editor.scss
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,11 @@

h2.wc-block-mini-cart__title {
@include font-size(larger);
margin: $gap-largest $gap 0;

.block-editor-block-list__layout {
display: flex;
align-items: baseline;
}
}

table.wc-block-cart-items {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import './empty-mini-cart-contents-block';
import './filled-mini-cart-contents-block';
import './mini-cart-title-block';
import './mini-cart-title-items-counter-block';
import './mini-cart-title-label-block';
import './mini-cart-items-block';
import './mini-cart-products-table-block';
import './mini-cart-footer-block';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ import { getIconsFromPaymentMethods } from '@woocommerce/base-utils';
import { getSetting } from '@woocommerce/settings';
import { PaymentEventsProvider } from '@woocommerce/base-context';
import classNames from 'classnames';
import { isObject } from '@woocommerce/types';

/**
* Internal dependencies
*/
import CartButton from '../mini-cart-cart-button-block/block';
import CheckoutButton from '../mini-cart-checkout-button-block/block';
import { hasChildren } from '../utils';

const PaymentMethodIconsElement = (): JSX.Element => {
const { paymentMethods } = usePaymentMethods();
Expand All @@ -37,18 +37,6 @@ interface Props {
checkoutButtonLabel: string;
}

/**
* Checks if there are any children that are blocks.
*/
const hasChildren = ( children ): boolean => {
return children.some( ( child ) => {
if ( Array.isArray( child ) ) {
return hasChildren( child );
}
return isObject( child ) && child.key !== null;
} );
};

const Block = ( {
children,
className,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,34 +1,45 @@
/**
* External dependencies
*/
import { sprintf, _n, __ } from '@wordpress/i18n';
import { useStoreCart } from '@woocommerce/base-context/hooks';
import classNames from 'classnames';

/**
* Internal dependencies
*/
import TitleItemsCounter from '../mini-cart-title-items-counter-block/block';
import TitleYourCart from '../mini-cart-title-label-block/block';
import { hasChildren } from '../utils';

type MiniCartTitleBlockProps = {
className: string;
children: JSX.Element;
};

const Block = ( { className }: MiniCartTitleBlockProps ): JSX.Element => {
const { cartItemsCount, cartIsLoading } = useStoreCart();
const Block = ( {
children,
className,
}: MiniCartTitleBlockProps ): JSX.Element | null => {
const { cartIsLoading } = useStoreCart();
if ( cartIsLoading ) {
return null;
}

// The `Mini Cart Title` was converted to two inner blocks, but we still need to render the old title for
// themes that have the old `mini-cart.html` template. So we check if there are any inner blocks and if
// not, render the title blocks.
const hasTitleInnerBlocks = hasChildren( children );

return (
<h2 className={ classNames( className, 'wc-block-mini-cart__title' ) }>
{ cartIsLoading
? __( 'Your cart', 'woo-gutenberg-products-block' )
: sprintf(
/* translators: %d is the count of items in the cart. */
_n(
'Your cart (%d item)',
'Your cart (%d items)',
cartItemsCount,
'woo-gutenberg-products-block'
),
cartItemsCount
) }
{ hasTitleInnerBlocks ? (
children
) : (
<>
<TitleYourCart />
<TitleItemsCounter />
</>
) }
</h2>
);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,36 @@
/**
* External dependencies
*/
import { useBlockProps } from '@wordpress/block-editor';

/**
* Internal dependencies
*/
import Block from './block';
import { InnerBlocks, useBlockProps } from '@wordpress/block-editor';

export const Edit = (): JSX.Element => {
const blockProps = useBlockProps();
const blockProps = useBlockProps( {
className: 'wc-block-mini-cart__title',
} );

const TEMPLATE = [
[ 'woocommerce/mini-cart-title-label-block', {} ],
[ 'woocommerce/mini-cart-title-items-counter-block', {} ],
];

return (
<div { ...blockProps }>
<Block />
</div>
<h2 { ...blockProps }>
<InnerBlocks
allowedBlocks={ [
'woocommerce/mini-cart-title-label-block',
'woocommerce/mini-cart-title-items-counter-block',
] }
template={ TEMPLATE }
templateLock="all"
/>
</h2>
);
};

export const Save = (): JSX.Element => {
return <div { ...useBlockProps.save() }></div>;
return (
<div { ...useBlockProps.save() }>
<InnerBlocks.Content />
</div>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"name": "woocommerce/mini-cart-title-items-counter-block",
"version": "1.0.0",
"title": "Mini Cart Title Items Counter",
"description": "Block that displays the items counter part of the Mini Cart Title block.",
"category": "woocommerce",
"supports": {
"align": false,
"html": false,
"multiple": false,
"reusable": false,
"inserter": false,
"lock": false,
"color": {
"text": true,
"background": true
},
"typography": {
"fontSize": true
},
"spacing": {
"padding": true
}
},
"parent": [ "woocommerce/mini-cart-title-block" ],
"textdomain": "woo-gutenberg-products-block",
"apiVersion": 2,
"$schema": "https://schemas.wp.org/trunk/block.json"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/**
* External dependencies
*/
import { useStoreCart } from '@woocommerce/base-context';
import classNames from 'classnames';
import { _n, sprintf } from '@wordpress/i18n';
import {
useColorProps,
useSpacingProps,
useTypographyProps,
} from '@woocommerce/base-hooks';

type Props = {
className?: string;
};

const Block = ( props: Props ): JSX.Element => {
const { cartItemsCount } = useStoreCart();
const colorProps = useColorProps( props );
const typographyProps = useTypographyProps( props );
const spacingProps = useSpacingProps( props );

return (
<span
className={ classNames(
props.className,
colorProps.className,
typographyProps.className
) }
style={ {
...colorProps.style,
...typographyProps.style,
...spacingProps.style,
} }
>
{ sprintf(
/* translators: %d is the count of items in the cart. */
_n(
'(%d item)',
'(%d items)',
cartItemsCount,
'woo-gutenberg-products-block'
),
cartItemsCount
) }
</span>
);
};

export default Block;
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* External dependencies
*/
import { useBlockProps } from '@wordpress/block-editor';
import { _n, sprintf } from '@wordpress/i18n';
import { useStoreCart } from '@woocommerce/base-context';

export const Edit = (): JSX.Element => {
const blockProps = useBlockProps();
const { cartItemsCount } = useStoreCart();

return (
<span { ...blockProps }>
{ sprintf(
/* translators: %d is the count of items in the cart. */
_n(
'(%d item)',
'(%d items)',
cartItemsCount,
'woo-gutenberg-products-block'
),
cartItemsCount
) }
</span>
);
};

export const Save = (): JSX.Element => {
return <div { ...useBlockProps.save() }></div>;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/**
* External dependencies
*/
import { Icon, heading } from '@wordpress/icons';
import { registerBlockType } from '@wordpress/blocks';

/**
* Internal dependencies
*/
import { Edit, Save } from './edit';

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore -- TypeScript expects some required properties which we already
// registered in PHP.
registerBlockType( 'woocommerce/mini-cart-title-items-counter-block', {
icon: {
src: (
<Icon
icon={ heading }
className="wc-block-editor-components-block-icon"
/>
),
},
edit: Edit,
save: Save,
} );
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* Internal dependencies
*/
import { defaultYourCartLabel } from './constants';

export default {
label: {
type: 'string',
default: defaultYourCartLabel,
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"name": "woocommerce/mini-cart-title-label-block",
"version": "1.0.0",
"title": "Mini Cart Title Label",
"description": "Block that displays the 'Your cart' part of the Mini Cart Title block.",
"category": "woocommerce",
"supports": {
"align": false,
"html": false,
"multiple": false,
"reusable": false,
"inserter": false,
"lock": false,
"color": {
"text": true,
"background": true
},
"typography": {
"fontSize": true
},
"spacing": {
"padding": true
}
},
"attributes": {
"label": {
"type": "string"
}
},
"parent": [ "woocommerce/mini-cart-title-block" ],
"textdomain": "woo-gutenberg-products-block",
"apiVersion": 2,
"$schema": "https://schemas.wp.org/trunk/block.json"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/**
* External dependencies
*/
import {
useColorProps,
useSpacingProps,
useTypographyProps,
} from '@woocommerce/base-hooks';
import classNames from 'classnames';

/**
* Internal dependencies
*/
import { defaultYourCartLabel } from './constants';

type Props = {
label?: string;
className?: string;
};

const Block = ( props: Props ): JSX.Element => {
const colorProps = useColorProps( props );
const typographyProps = useTypographyProps( props );
const spacingProps = useSpacingProps( props );

return (
<span
className={ classNames(
props.className,
colorProps.className,
typographyProps.className
) }
style={ {
...colorProps.style,
...typographyProps.style,
...spacingProps.style,
} }
>
{ props.label || defaultYourCartLabel }
</span>
);
};

export default Block;
Loading

0 comments on commit 2300e1f

Please sign in to comment.