diff --git a/assets/js/blocks/catalog-sorting/block.json b/assets/js/blocks/catalog-sorting/block.json
new file mode 100644
index 00000000000..6d46b51b93e
--- /dev/null
+++ b/assets/js/blocks/catalog-sorting/block.json
@@ -0,0 +1,27 @@
+{
+ "name": "woocommerce/catalog-sorting",
+ "version": "1.0.0",
+ "title": "Catalog Sorting",
+ "description": "Enable customers to change the sorting order of the products.",
+ "category": "woocommerce",
+ "keywords": [ "WooCommerce" ],
+ "supports": {
+ "color": {
+ "text": true,
+ "background": false
+ },
+ "typography": {
+ "fontSize": true,
+ "__experimentalFontFamily": true
+ }
+ },
+ "attributes": {
+ "fontSize": {
+ "type": "string",
+ "default": "small"
+ }
+ },
+ "textdomain": "woo-gutenberg-products-block",
+ "apiVersion": 2,
+ "$schema": "https://schemas.wp.org/trunk/block.json"
+}
diff --git a/assets/js/blocks/catalog-sorting/edit.tsx b/assets/js/blocks/catalog-sorting/edit.tsx
new file mode 100644
index 00000000000..c0b1de6f1c7
--- /dev/null
+++ b/assets/js/blocks/catalog-sorting/edit.tsx
@@ -0,0 +1,34 @@
+/**
+ * External dependencies
+ */
+import { useBlockProps } from '@wordpress/block-editor';
+import { Disabled } from '@wordpress/components';
+import { __ } from '@wordpress/i18n';
+
+const CatalogSorting = () => {
+ return (
+
+ );
+};
+
+const Edit = () => {
+ const blockProps = useBlockProps( {
+ className: 'woocommerce wc-block-catalog-sorting',
+ } );
+
+ return (
+ <>
+
+
+
+
+
+ >
+ );
+};
+
+export default Edit;
diff --git a/assets/js/blocks/catalog-sorting/index.tsx b/assets/js/blocks/catalog-sorting/index.tsx
new file mode 100644
index 00000000000..b83b17bf6af
--- /dev/null
+++ b/assets/js/blocks/catalog-sorting/index.tsx
@@ -0,0 +1,30 @@
+/**
+ * External dependencies
+ */
+import { registerBlockType } from '@wordpress/blocks';
+import { Icon } from '@wordpress/icons';
+import { totals } from '@woocommerce/icons';
+
+/**
+ * Internal dependencies
+ */
+import metadata from './block.json';
+import edit from './edit';
+
+registerBlockType( metadata, {
+ icon: {
+ src: (
+
+ ),
+ },
+ attributes: {
+ ...metadata.attributes,
+ },
+ edit,
+ save() {
+ return null;
+ },
+} );
diff --git a/assets/js/blocks/catalog-sorting/style.scss b/assets/js/blocks/catalog-sorting/style.scss
new file mode 100644
index 00000000000..cc8ad305a9c
--- /dev/null
+++ b/assets/js/blocks/catalog-sorting/style.scss
@@ -0,0 +1,11 @@
+.woocommerce.wc-block-catalog-sorting {
+ form {
+ float: none;
+ }
+
+ select {
+ color: inherit !important;
+ font-size: inherit;
+ font-family: inherit;
+ }
+}
diff --git a/bin/webpack-entries.js b/bin/webpack-entries.js
index d2cf0158e0f..2fb20bc3111 100644
--- a/bin/webpack-entries.js
+++ b/bin/webpack-entries.js
@@ -21,6 +21,7 @@ const blocks = {
},
'attribute-filter': {},
cart: {},
+ 'catalog-sorting': {},
checkout: {},
'customer-account': {},
'featured-category': {
diff --git a/src/BlockTypes/CatalogSorting.php b/src/BlockTypes/CatalogSorting.php
new file mode 100644
index 00000000000..607a35a424a
--- /dev/null
+++ b/src/BlockTypes/CatalogSorting.php
@@ -0,0 +1,56 @@
+%4$s',
+ esc_attr( $classes_and_styles['classes'] ),
+ esc_attr( $classname ),
+ esc_attr( $classes_and_styles['styles'] ),
+ $catalog_sorting
+ );
+ }
+
+ /**
+ * 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;
+ }
+}
diff --git a/src/BlockTypesController.php b/src/BlockTypesController.php
index 0814208ad89..e101f1b75d1 100644
--- a/src/BlockTypesController.php
+++ b/src/BlockTypesController.php
@@ -168,6 +168,7 @@ protected function get_block_types() {
'AllProducts',
'AllReviews',
'AttributeFilter',
+ 'CatalogSorting',
'ClassicTemplate',
'CustomerAccount',
'FeaturedCategory',
@@ -246,6 +247,7 @@ protected function get_block_types() {
$block_types = array_diff(
$block_types,
[
+ 'CatalogSorting',
'ClassicTemplate',
]
);
diff --git a/tests/e2e/specs/backend/catalog-sorting.test.js b/tests/e2e/specs/backend/catalog-sorting.test.js
new file mode 100644
index 00000000000..7f2bbefb583
--- /dev/null
+++ b/tests/e2e/specs/backend/catalog-sorting.test.js
@@ -0,0 +1,66 @@
+/**
+ * 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: 'Catalog Sorting',
+ slug: 'woocommerce/catalog-sorting',
+ class: '.wc-block-catalog-sorting',
+};
+
+describe( `${ block.name } Block`, () => {
+ describe( 'in a post', () => {
+ beforeAll( async () => {
+ await switchUserToAdmin();
+ } );
+
+ it( 'can not be inserted', async () => {
+ 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 );
+ } );
+ } );
+} );
diff --git a/tests/e2e/specs/backend/customer-account.js b/tests/e2e/specs/backend/customer-account.test.js
similarity index 100%
rename from tests/e2e/specs/backend/customer-account.js
rename to tests/e2e/specs/backend/customer-account.test.js