diff --git a/lib/compat/wordpress-5.8/index.php b/lib/compat/wordpress-5.8/index.php
index 29a97fb20de81..35b0f11eeae1f 100644
--- a/lib/compat/wordpress-5.8/index.php
+++ b/lib/compat/wordpress-5.8/index.php
@@ -164,3 +164,39 @@ function gutenberg_register_legacy_query_loop_block() {
add_action( 'init', 'gutenberg_register_legacy_query_loop_block' );
}
+
+if ( ! function_exists( 'get_query_pagination_arrow' ) ) {
+ /**
+ * Helper function that returns the proper pagination arrow html for
+ * `QueryPaginationNext` and `QueryPaginationPrevious` blocks based
+ * on the provided `paginationArrow` from `QueryPagination` context.
+ *
+ * It's used in QueryPaginationNext and QueryPaginationPrevious blocks.
+ *
+ * @param WP_Block $block Block instance.
+ * @param boolean $is_next Flag for hanlding `next/previous` blocks.
+ *
+ * @return string|null Returns the constructed WP_Query arguments.
+ */
+ function get_query_pagination_arrow( $block, $is_next ) {
+ $arrow_map = array(
+ 'none' => '',
+ 'arrow' => array(
+ 'next' => '→',
+ 'previous' => '←',
+ ),
+ 'chevron' => array(
+ 'next' => '»',
+ 'previous' => '«',
+ ),
+ );
+ if ( ! empty( $block->context['paginationArrow'] ) && array_key_exists( $block->context['paginationArrow'], $arrow_map ) && ! empty( $arrow_map[ $block->context['paginationArrow'] ] ) ) {
+ $pagination_type = $is_next ? 'next' : 'previous';
+ $arrow_attribute = $block->context['paginationArrow'];
+ $arrow = $arrow_map[ $block->context['paginationArrow'] ][ $pagination_type ];
+ $arrow_classes = "wp-block-query-pagination-$pagination_type-arrow is-arrow-$arrow_attribute";
+ return "$arrow";
+ }
+ return null;
+ }
+}
diff --git a/packages/block-library/src/query-pagination-next/block.json b/packages/block-library/src/query-pagination-next/block.json
index afc69d6e14a3b..f7d4850413222 100644
--- a/packages/block-library/src/query-pagination-next/block.json
+++ b/packages/block-library/src/query-pagination-next/block.json
@@ -11,7 +11,7 @@
"type": "string"
}
},
- "usesContext": [ "queryId", "query" ],
+ "usesContext": [ "queryId", "query", "paginationArrow" ],
"supports": {
"reusable": false,
"html": false,
diff --git a/packages/block-library/src/query-pagination-next/edit.js b/packages/block-library/src/query-pagination-next/edit.js
index 4e48c0bcecaa6..d91f3d7e0ba30 100644
--- a/packages/block-library/src/query-pagination-next/edit.js
+++ b/packages/block-library/src/query-pagination-next/edit.js
@@ -4,19 +4,41 @@
import { __ } from '@wordpress/i18n';
import { useBlockProps, PlainText } from '@wordpress/block-editor';
+const arrowMap = {
+ none: '',
+ arrow: '→',
+ chevron: '»',
+};
+
export default function QueryPaginationNextEdit( {
attributes: { label },
setAttributes,
+ context: { paginationArrow },
} ) {
+ const displayArrow = arrowMap[ paginationArrow ];
return (
- setAttributes( { label: newLabel } ) }
+ event.preventDefault() }
{ ...useBlockProps() }
- />
+ >
+
+ setAttributes( { label: newLabel } )
+ }
+ />
+ { displayArrow && (
+
+ { displayArrow }
+
+ ) }
+
);
}
diff --git a/packages/block-library/src/query-pagination-next/index.php b/packages/block-library/src/query-pagination-next/index.php
index 7b0b4051f1aac..d091e1c6bbc0f 100644
--- a/packages/block-library/src/query-pagination-next/index.php
+++ b/packages/block-library/src/query-pagination-next/index.php
@@ -22,7 +22,11 @@ function render_block_core_query_pagination_next( $attributes, $content, $block
$wrapper_attributes = get_block_wrapper_attributes();
$default_label = __( 'Next Page' );
$label = isset( $attributes['label'] ) && ! empty( $attributes['label'] ) ? $attributes['label'] : $default_label;
- $content = '';
+ $pagination_arrow = get_query_pagination_arrow( $block, true );
+ if ( $pagination_arrow ) {
+ $label .= $pagination_arrow;
+ }
+ $content = '';
// Check if the pagination is for Query that inherits the global context.
if ( isset( $block->context['query']['inherit'] ) && $block->context['query']['inherit'] ) {
diff --git a/packages/block-library/src/query-pagination-previous/block.json b/packages/block-library/src/query-pagination-previous/block.json
index 78a53867d0b7a..c3a05cc202d30 100644
--- a/packages/block-library/src/query-pagination-previous/block.json
+++ b/packages/block-library/src/query-pagination-previous/block.json
@@ -11,7 +11,7 @@
"type": "string"
}
},
- "usesContext": [ "queryId", "query" ],
+ "usesContext": [ "queryId", "query", "paginationArrow" ],
"supports": {
"reusable": false,
"html": false,
diff --git a/packages/block-library/src/query-pagination-previous/edit.js b/packages/block-library/src/query-pagination-previous/edit.js
index 2c0bf33005de8..c695a453ce1e3 100644
--- a/packages/block-library/src/query-pagination-previous/edit.js
+++ b/packages/block-library/src/query-pagination-previous/edit.js
@@ -4,19 +4,41 @@
import { __ } from '@wordpress/i18n';
import { useBlockProps, PlainText } from '@wordpress/block-editor';
+const arrowMap = {
+ none: '',
+ arrow: '←',
+ chevron: '«',
+};
+
export default function QueryPaginationPreviousEdit( {
attributes: { label },
setAttributes,
+ context: { paginationArrow },
} ) {
+ const displayArrow = arrowMap[ paginationArrow ];
return (
- setAttributes( { label: newLabel } ) }
+ event.preventDefault() }
{ ...useBlockProps() }
- />
+ >
+ { displayArrow && (
+
+ { displayArrow }
+
+ ) }
+
+ setAttributes( { label: newLabel } )
+ }
+ />
+
);
}
diff --git a/packages/block-library/src/query-pagination-previous/index.php b/packages/block-library/src/query-pagination-previous/index.php
index ac319d0be4dbf..47506496722d8 100644
--- a/packages/block-library/src/query-pagination-previous/index.php
+++ b/packages/block-library/src/query-pagination-previous/index.php
@@ -21,7 +21,11 @@ function render_block_core_query_pagination_previous( $attributes, $content, $bl
$wrapper_attributes = get_block_wrapper_attributes();
$default_label = __( 'Previous Page' );
$label = isset( $attributes['label'] ) && ! empty( $attributes['label'] ) ? $attributes['label'] : $default_label;
- $content = '';
+ $pagination_arrow = get_query_pagination_arrow( $block, false );
+ if ( $pagination_arrow ) {
+ $label = $pagination_arrow . $label;
+ }
+ $content = '';
// Check if the pagination is for Query that inherits the global context
// and handle appropriately.
if ( isset( $block->context['query']['inherit'] ) && $block->context['query']['inherit'] ) {
diff --git a/packages/block-library/src/query-pagination/block.json b/packages/block-library/src/query-pagination/block.json
index c1de24977f37f..45b7a42bffbad 100644
--- a/packages/block-library/src/query-pagination/block.json
+++ b/packages/block-library/src/query-pagination/block.json
@@ -6,7 +6,16 @@
"parent": [ "core/query" ],
"description": "Displays a paginated navigation to next/previous set of posts, when applicable.",
"textdomain": "default",
+ "attributes": {
+ "paginationArrow": {
+ "type": "string",
+ "default": "none"
+ }
+ },
"usesContext": [ "queryId", "query" ],
+ "providesContext": {
+ "paginationArrow": "paginationArrow"
+ },
"supports": {
"align": true,
"reusable": false,
diff --git a/packages/block-library/src/query-pagination/edit.js b/packages/block-library/src/query-pagination/edit.js
index 47ac55f30693a..c3f4f53f5f2b3 100644
--- a/packages/block-library/src/query-pagination/edit.js
+++ b/packages/block-library/src/query-pagination/edit.js
@@ -1,10 +1,20 @@
/**
* WordPress dependencies
*/
+import { __ } from '@wordpress/i18n';
import {
+ InspectorControls,
useBlockProps,
__experimentalUseInnerBlocksProps as useInnerBlocksProps,
+ store as blockEditorStore,
} from '@wordpress/block-editor';
+import { useSelect } from '@wordpress/data';
+import { PanelBody } from '@wordpress/components';
+
+/**
+ * Internal dependencies
+ */
+import { QueryPaginationArrowControls } from './query-pagination-arrow-controls';
const TEMPLATE = [
[ 'core/query-pagination-previous' ],
@@ -12,7 +22,25 @@ const TEMPLATE = [
[ 'core/query-pagination-next' ],
];
-export default function QueryPaginationEdit() {
+export default function QueryPaginationEdit( {
+ attributes: { paginationArrow },
+ setAttributes,
+ clientId,
+} ) {
+ const hasNextPreviousBlocks = useSelect( ( select ) => {
+ const { getBlocks } = select( blockEditorStore );
+ const innerBlocks = getBlocks( clientId );
+ /**
+ * Show the `paginationArrow` control only if a
+ * `QueryPaginationNext/Previous` block exists.
+ */
+ return innerBlocks?.find( ( innerBlock ) => {
+ return [
+ 'core/query-pagination-next',
+ 'core/query-pagination-previous',
+ ].includes( innerBlock.name );
+ } );
+ }, [] );
const blockProps = useBlockProps();
const innerBlocksProps = useInnerBlocksProps( blockProps, {
template: TEMPLATE,
@@ -23,5 +51,21 @@ export default function QueryPaginationEdit() {
],
orientation: 'horizontal',
} );
- return ;
+ return (
+ <>
+ { hasNextPreviousBlocks && (
+
+
+ {
+ setAttributes( { paginationArrow: value } );
+ } }
+ />
+
+
+ ) }
+
+ >
+ );
}
diff --git a/packages/block-library/src/query-pagination/query-pagination-arrow-controls.js b/packages/block-library/src/query-pagination/query-pagination-arrow-controls.js
new file mode 100644
index 0000000000000..28ae36ed41572
--- /dev/null
+++ b/packages/block-library/src/query-pagination/query-pagination-arrow-controls.js
@@ -0,0 +1,44 @@
+/**
+ * WordPress dependencies
+ */
+import { __, _x } from '@wordpress/i18n';
+import {
+ __experimentalToggleGroupControl as ToggleGroupControl,
+ __experimentalToggleGroupControlOption as ToggleGroupControlOption,
+} from '@wordpress/components';
+
+export function QueryPaginationArrowControls( { value, onChange } ) {
+ return (
+
+
+
+
+
+ );
+}
diff --git a/packages/block-library/src/query-pagination/style.scss b/packages/block-library/src/query-pagination/style.scss
index e140863a7d981..5a4a950757cd7 100644
--- a/packages/block-library/src/query-pagination/style.scss
+++ b/packages/block-library/src/query-pagination/style.scss
@@ -18,4 +18,22 @@ $pagination-margin: 0.5em;
margin-right: 0;
}
}
+ .wp-block-query-pagination-previous-arrow {
+ margin-right: 1ch;
+ display: inline-block; // Needed so that the transform works.
+ // chevron(`»`) symbol doesn't need the mirroring by us.
+ &:not(.is-arrow-chevron) {
+ // Flip for RTL.
+ transform: scaleX(1) #{"/*rtl:scaleX(-1);*/"}; // This points the arrow right for LTR and left for RTL.
+ }
+ }
+ .wp-block-query-pagination-next-arrow {
+ margin-left: 1ch;
+ display: inline-block; // Needed so that the transform works.
+ // chevron(`»`) symbol doesn't need the mirroring by us.
+ &:not(.is-arrow-chevron) {
+ // Flip for RTL.
+ transform: scaleX(1) #{"/*rtl:scaleX(-1);*/"}; // This points the arrow right for LTR and left for RTL.
+ }
+ }
}
diff --git a/test/integration/fixtures/blocks/core__query-pagination.json b/test/integration/fixtures/blocks/core__query-pagination.json
index a5ade7819c893..9a5c156770fbf 100644
--- a/test/integration/fixtures/blocks/core__query-pagination.json
+++ b/test/integration/fixtures/blocks/core__query-pagination.json
@@ -3,7 +3,9 @@
"clientId": "_clientId_0",
"name": "core/query-pagination",
"isValid": true,
- "attributes": {},
+ "attributes": {
+ "paginationArrow": "none"
+ },
"innerBlocks": [],
"originalContent": ""
}