Skip to content

Commit

Permalink
List View: Add media previews to list view for gallery and image bloc…
Browse files Browse the repository at this point in the history
…ks (#53381)

* List View: Add images

* Add some styling and a max number of images

* Tweak styling

* Add image count

* Reduce to 3 images, remove image count
  • Loading branch information
andrewserong committed Aug 10, 2023
1 parent 5f92554 commit e522dd9
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import useBlockDisplayTitle from '../block-title/use-block-display-title';
import ListViewExpander from './expander';
import { useBlockLock } from '../block-lock';
import { store as blockEditorStore } from '../../store';
import useListViewImages from './use-list-view-images';

function ListViewBlockSelectButton(
{
Expand Down Expand Up @@ -63,6 +64,7 @@ function ListViewBlockSelectButton(
const { removeBlocks } = useDispatch( blockEditorStore );
const isMatch = useShortcutEventMatch();
const isSticky = blockInformation?.positionType === 'sticky';
const images = useListViewImages( { clientId, isExpanded } );

const positionLabel = blockInformation?.positionLabel
? sprintf(
Expand Down Expand Up @@ -184,6 +186,23 @@ function ListViewBlockSelectButton(
</span>
</Tooltip>
) }
{ images.length ? (
<span
className="block-editor-list-view-block-select-button__images"
aria-hidden
>
{ images.map( ( image, index ) => (
<span
className="block-editor-list-view-block-select-button__image"
key={ `img-${ image.url }` }
style={ {
backgroundImage: `url(${ image.url })`,
zIndex: images.length - index, // Ensure the first image is on top, and subsequent images are behind.
} }
/>
) ) }
</span>
) : null }
{ isLocked && (
<span className="block-editor-list-view-block-select-button__lock">
<Icon icon={ lock } />
Expand Down
25 changes: 25 additions & 0 deletions packages/block-editor/src/components/list-view/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,31 @@
.block-editor-list-view-block-select-button__sticky {
line-height: 0;
}

.block-editor-list-view-block-select-button__images {
display: flex;
}

.block-editor-list-view-block-select-button__image {
background-size: cover;
width: 20px;
height: 20px;
border-radius: $radius-block-ui;

&:not(:only-child) {
box-shadow: 0 0 0 $radius-block-ui $white;
}

&:not(:first-child) {
margin-left: -5px;
}
}

&.is-selected .block-editor-list-view-block-select-button__image {
&:not(:only-child) {
box-shadow: 0 0 0 $radius-block-ui var(--wp-admin-theme-color);
}
}
}

.block-editor-list-view-block__contents-cell,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/**
* WordPress dependencies
*/
import { useMemo } from '@wordpress/element';
import { useSelect } from '@wordpress/data';

/**
* Internal dependencies
*/
import { store as blockEditorStore } from '../../store';

// Maximum number of images to display in a list view row.
const MAX_IMAGES = 3;

function getImageUrl( block ) {
if ( block.name !== 'core/image' ) {
return;
}

if ( block.attributes?.url ) {
return { url: block.attributes.url, alt: block.attributes.alt };
}
}

function getImagesFromGallery( block ) {
if ( block.name !== 'core/gallery' || ! block.innerBlocks ) {
return [];
}

const images = [];

for ( const innerBlock of block.innerBlocks ) {
const img = getImageUrl( innerBlock );
if ( img ) {
images.push( img );
}
if ( images.length >= MAX_IMAGES ) {
return images;
}
}

return images;
}

function getImagesFromBlock( block, isExpanded ) {
const img = getImageUrl( block );
if ( img ) {
return [ img ];
}
return isExpanded ? [] : getImagesFromGallery( block );
}

/**
* Get a block's preview images for display within a list view row.
*
* TODO: Currently only supports images from the core/image and core/gallery
* blocks. This should be expanded to support other blocks that have images,
* potentially via an API that blocks can opt into / provide their own logic.
*
* @param {Object} props Hook properties.
* @param {string} props.clientId The block's clientId.
* @param {boolean} props.isExpanded Whether or not the block is expanded in the list view.
* @return {Array} Images.
*/
export default function useListViewImages( { clientId, isExpanded } ) {
const { block } = useSelect(
( select ) => {
const _block = select( blockEditorStore ).getBlock( clientId );
return { block: _block };
},
[ clientId ]
);

const images = useMemo( () => {
return getImagesFromBlock( block, isExpanded );
}, [ block, isExpanded ] );

return images;
}

0 comments on commit e522dd9

Please sign in to comment.