diff --git a/packages/block-library/src/post-featured-image/style.scss b/packages/block-library/src/post-featured-image/style.scss
index eaa2b5f413733..1deddff9a9fec 100644
--- a/packages/block-library/src/post-featured-image/style.scss
+++ b/packages/block-library/src/post-featured-image/style.scss
@@ -2,4 +2,8 @@
a {
display: inline-block;
}
+ img {
+ max-width: 100%;
+ height: auto;
+ }
}
diff --git a/packages/block-library/src/query-loop/block.json b/packages/block-library/src/query-loop/block.json
index 963afbe71c630..5373403ea79a5 100644
--- a/packages/block-library/src/query-loop/block.json
+++ b/packages/block-library/src/query-loop/block.json
@@ -5,7 +5,8 @@
"usesContext": [
"queryId",
"query",
- "queryContext"
+ "queryContext",
+ "layout"
],
"supports": {
"reusable": false,
diff --git a/packages/block-library/src/query-loop/edit.js b/packages/block-library/src/query-loop/edit.js
index a87b8b33ca13d..a32ffd6741050 100644
--- a/packages/block-library/src/query-loop/edit.js
+++ b/packages/block-library/src/query-loop/edit.js
@@ -1,3 +1,8 @@
+/**
+ * External dependencies
+ */
+import classnames from 'classnames';
+
/**
* WordPress dependencies
*/
@@ -38,6 +43,7 @@ export default function QueryLoopEdit( {
sticky,
} = {},
queryContext,
+ layout: { type: layoutType = 'flex', columns = 1 } = {},
},
} ) {
const [ { page } ] = useQueryContext() || queryContext || [ {} ];
@@ -102,7 +108,13 @@ export default function QueryLoopEdit( {
} ) ),
[ posts ]
);
- const blockProps = useBlockProps();
+ const hasLayoutFlex = layoutType === 'flex' && columns > 1;
+ const blockProps = useBlockProps( {
+ className: classnames( {
+ 'is-flex-container': hasLayoutFlex,
+ [ `columns-${ columns }` ]: hasLayoutFlex,
+ } ),
+ } );
const innerBlocksProps = useInnerBlocksProps( {}, { template: TEMPLATE } );
if ( ! posts ) {
@@ -114,7 +126,7 @@ export default function QueryLoopEdit( {
}
return (
-
+
{ blockContexts &&
blockContexts.map( ( blockContext ) => (
{ blockContext ===
( activeBlockContext || blockContexts[ 0 ] ) ? (
-
+
) : (
-
- setActiveBlockContext( blockContext )
- }
- />
+ -
+
+ setActiveBlockContext( blockContext )
+ }
+ />
+
) }
) ) }
-
+
);
}
diff --git a/packages/block-library/src/query-loop/editor.scss b/packages/block-library/src/query-loop/editor.scss
index 294eb615109be..39a614277d58d 100644
--- a/packages/block-library/src/query-loop/editor.scss
+++ b/packages/block-library/src/query-loop/editor.scss
@@ -1,3 +1,5 @@
-.editor-styles-wrapper .wp-block.wp-block-query-loop {
+.wp-block.wp-block-query-loop {
max-width: 100%;
+ padding-left: 0;
+ list-style: none;
}
diff --git a/packages/block-library/src/query-loop/index.php b/packages/block-library/src/query-loop/index.php
index 5acc340bd66e2..d1aef57b1cb66 100644
--- a/packages/block-library/src/query-loop/index.php
+++ b/packages/block-library/src/query-loop/index.php
@@ -69,9 +69,18 @@ function render_block_core_query_loop( $attributes, $content, $block ) {
$posts = get_posts( $query );
+ $classnames = '';
+ if ( isset( $block->context['layout'] ) && isset( $block->context['query'] ) ) {
+ if ( isset( $block->context['layout']['type'] ) && 'flex' === $block->context['layout']['type'] ) {
+ $classnames = "is-flex-container columns-{$block->context['layout']['columns']}";
+ }
+ }
+
+ $wrapper_attributes = get_block_wrapper_attributes( array( 'class' => $classnames ) );
+
$content = '';
foreach ( $posts as $post ) {
- $content .= (
+ $block_content = (
new WP_Block(
$block->parsed_block,
array(
@@ -80,8 +89,13 @@ function render_block_core_query_loop( $attributes, $content, $block ) {
)
)
)->render( array( 'dynamic' => false ) );
+ $content .= "{$block_content}";
}
- return $content;
+ return sprintf(
+ '',
+ $wrapper_attributes,
+ $content
+ );
}
/**
diff --git a/packages/block-library/src/query-loop/style.scss b/packages/block-library/src/query-loop/style.scss
new file mode 100644
index 0000000000000..40413f4041a27
--- /dev/null
+++ b/packages/block-library/src/query-loop/style.scss
@@ -0,0 +1,32 @@
+.wp-block-query-loop {
+ max-width: 100%;
+ list-style: none;
+ padding: 0;
+
+ li {
+ clear: both;
+ }
+
+ &.is-flex-container {
+ flex-direction: row;
+ display: flex;
+ flex-wrap: wrap;
+
+ li {
+ margin: 0 1.25em 1.25em 0;
+ width: 100%;
+ }
+
+ @include break-small {
+ @for $i from 2 through 6 {
+ &.is-flex-container.columns-#{ $i } > li {
+ width: calc((100% / #{ $i }) - 1.25em + (1.25em / #{ $i }));
+
+ &:nth-child( #{ $i }n ) {
+ margin-right: 0;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/packages/block-library/src/query/block.json b/packages/block-library/src/query/block.json
index f01c6b66081e3..7477e03d6f848 100644
--- a/packages/block-library/src/query/block.json
+++ b/packages/block-library/src/query/block.json
@@ -22,11 +22,18 @@
"exclude": [],
"sticky": ""
}
+ },
+ "layout": {
+ "type": "object",
+ "default": {
+ "type": "list"
+ }
}
},
"providesContext": {
"queryId": "queryId",
- "query": "query"
+ "query": "query",
+ "layout": "layout"
},
"usesContext": [
"postId"
diff --git a/packages/block-library/src/query/edit/index.js b/packages/block-library/src/query/edit/index.js
index 40b9cc4ab755d..45be4c7f88537 100644
--- a/packages/block-library/src/query/edit/index.js
+++ b/packages/block-library/src/query/edit/index.js
@@ -21,10 +21,11 @@ import { DEFAULTS_POSTS_PER_PAGE } from '../constants';
const TEMPLATE = [ [ 'core/query-loop' ] ];
export function QueryContent( {
- attributes: { queryId, query },
+ attributes,
context: { postId },
setAttributes,
} ) {
+ const { queryId, query, layout } = attributes;
const instanceId = useInstanceId( QueryContent );
const blockProps = useBlockProps();
const innerBlocksProps = useInnerBlocksProps( {}, { template: TEMPLATE } );
@@ -59,11 +60,21 @@ export function QueryContent( {
}, [ queryId, instanceId ] );
const updateQuery = ( newQuery ) =>
setAttributes( { query: { ...query, ...newQuery } } );
+ const updateLayout = ( newLayout ) =>
+ setAttributes( { layout: { ...layout, ...newLayout } } );
return (
<>
-
+
-
+
diff --git a/packages/block-library/src/query/edit/query-inspector-controls.js b/packages/block-library/src/query/edit/query-inspector-controls.js
index a558884ca1f91..0be60543a6512 100644
--- a/packages/block-library/src/query/edit/query-inspector-controls.js
+++ b/packages/block-library/src/query/edit/query-inspector-controls.js
@@ -13,6 +13,8 @@ import {
TextControl,
FormTokenField,
SelectControl,
+ RangeControl,
+ Notice,
} from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import { InspectorControls } from '@wordpress/block-editor';
@@ -31,7 +33,11 @@ const stickyOptions = [
{ label: __( 'Only' ), value: 'only' },
];
-export default function QueryInspectorControls( { query, setQuery } ) {
+export default function QueryInspectorControls( {
+ attributes: { query, layout },
+ setQuery,
+ setLayout,
+} ) {
const {
order,
orderBy,
@@ -139,6 +145,26 @@ export default function QueryInspectorControls( { query, setQuery } ) {
label={ __( 'Post Type' ) }
onChange={ onPostTypeChange }
/>
+ { layout?.type === 'flex' && (
+ <>
+
+ setLayout( { columns: value } )
+ }
+ min={ 2 }
+ max={ Math.max( 6, layout.columns ) }
+ />
+ { layout.columns > 6 && (
+
+ { __(
+ 'This column count exceeds the recommended amount and may cause visual breakage.'
+ ) }
+
+ ) }
+ >
+ ) }
setQuery( { order: value } ) }
diff --git a/packages/block-library/src/query/edit/query-toolbar.js b/packages/block-library/src/query/edit/query-toolbar.js
index d4c5539df653f..dd079aa1a8110 100644
--- a/packages/block-library/src/query/edit/query-toolbar.js
+++ b/packages/block-library/src/query/edit/query-toolbar.js
@@ -10,66 +10,88 @@ import {
__experimentalNumberControl as NumberControl,
} from '@wordpress/components';
import { __ } from '@wordpress/i18n';
-import { settings } from '@wordpress/icons';
+import { settings, list, grid } from '@wordpress/icons';
-export default function QueryToolbar( { query, setQuery } ) {
+export default function QueryToolbar( {
+ attributes: { query, layout },
+ setQuery,
+ setLayout,
+} ) {
+ const layoutControls = [
+ {
+ icon: list,
+ title: __( 'List view' ),
+ onClick: () => setLayout( { type: 'list' } ),
+ isActive: layout?.type === 'list',
+ },
+ {
+ icon: grid,
+ title: __( 'Grid view' ),
+ onClick: () =>
+ setLayout( { type: 'flex', columns: layout?.columns || 3 } ),
+ isActive: layout?.type === 'flex',
+ },
+ ];
return (
-
- (
-
- ) }
- renderContent={ () => (
- <>
-
-
- setQuery( { perPage: +value ?? -1 } )
- }
- step="1"
- value={ query.perPage }
- isDragEnabled={ false }
- />
-
-
-
- setQuery( { offset: +value } )
- }
- step="1"
- value={ query.offset }
- isDragEnabled={ false }
- />
-
-
-
- setQuery( { pages: value ?? -1 } )
- }
- />
-
- >
- ) }
- />
-
+ <>
+
+ (
+
+ ) }
+ renderContent={ () => (
+ <>
+
+
+ setQuery( { perPage: +value ?? -1 } )
+ }
+ step="1"
+ value={ query.perPage }
+ isDragEnabled={ false }
+ />
+
+
+
+ setQuery( { offset: +value } )
+ }
+ step="1"
+ value={ query.offset }
+ isDragEnabled={ false }
+ />
+
+
+
+ setQuery( { pages: value ?? -1 } )
+ }
+ />
+
+ >
+ ) }
+ />
+
+
+ >
);
}
diff --git a/packages/block-library/src/style.scss b/packages/block-library/src/style.scss
index 899f51a4b688a..eeafa5502873c 100644
--- a/packages/block-library/src/style.scss
+++ b/packages/block-library/src/style.scss
@@ -26,6 +26,7 @@
@import "./paragraph/style.scss";
@import "./post-author/style.scss";
@import "./pullquote/style.scss";
+@import "./query-loop/style.scss";
@import "./quote/style.scss";
@import "./rss/style.scss";
@import "./search/style.scss";
diff --git a/packages/e2e-tests/fixtures/blocks/core__query.json b/packages/e2e-tests/fixtures/blocks/core__query.json
index 3e90d6a3f9c0f..235fcefff51e2 100644
--- a/packages/e2e-tests/fixtures/blocks/core__query.json
+++ b/packages/e2e-tests/fixtures/blocks/core__query.json
@@ -17,6 +17,9 @@
"search": "",
"exclude": [],
"sticky": ""
+ },
+ "layout": {
+ "type": "list"
}
},
"innerBlocks": [],