diff --git a/packages/block-library/src/gallery/edit.js b/packages/block-library/src/gallery/edit.js index a1b3b80b285ed6..eae1bfe610e27c 100644 --- a/packages/block-library/src/gallery/edit.js +++ b/packages/block-library/src/gallery/edit.js @@ -6,7 +6,7 @@ import classnames from 'classnames'; /** * WordPress dependencies */ -import { compose } from '@wordpress/compose'; +import { compose, usePrevious } from '@wordpress/compose'; import { BaseControl, PanelBody, @@ -14,6 +14,7 @@ import { ToggleControl, RangeControl, Spinner, + ToolbarButton, } from '@wordpress/components'; import { store as blockEditorStore, @@ -24,7 +25,13 @@ import { BlockControls, MediaReplaceFlow, } from '@wordpress/block-editor'; -import { Platform, useEffect, useMemo } from '@wordpress/element'; +import { + Platform, + useCallback, + useEffect, + useState, + useMemo, +} from '@wordpress/element'; import { __, _x, sprintf } from '@wordpress/i18n'; import { useSelect, useDispatch } from '@wordpress/data'; import { withViewportMatch } from '@wordpress/viewport'; @@ -32,6 +39,7 @@ import { View } from '@wordpress/primitives'; import { createBlock } from '@wordpress/blocks'; import { createBlobURL } from '@wordpress/blob'; import { store as noticesStore } from '@wordpress/notices'; +import { caption as captionIcon } from '@wordpress/icons'; /** * Internal dependencies @@ -83,9 +91,37 @@ function GalleryEdit( props ) { clientId, isSelected, insertBlocksAfter, + isContentLocked, } = props; - const { columns, imageCrop, linkTarget, linkTo, sizeSlug } = attributes; + const { columns, imageCrop, linkTarget, linkTo, sizeSlug, caption } = + attributes; + const [ showCaption, setShowCaption ] = useState( !! caption ); + const prevCaption = usePrevious( caption ); + + // We need to show the caption when changes come from + // history navigation(undo/redo). + useEffect( () => { + if ( caption && ! prevCaption ) { + setShowCaption( true ); + } + }, [ caption, prevCaption ] ); + + useEffect( () => { + if ( ! isSelected && ! caption ) { + setShowCaption( false ); + } + }, [ isSelected, caption ] ); + + // Focus the caption when we click to add one. + const captionRef = useCallback( + ( node ) => { + if ( node && ! caption ) { + node.focus(); + } + }, + [ caption ] + ); const { __unstableMarkNextChangeAsNotPersistent, @@ -574,6 +610,25 @@ function GalleryEdit( props ) { ) } + + { ! isContentLocked && ( + { + setShowCaption( ! showCaption ); + if ( showCaption && caption ) { + setAttributes( { caption: undefined } ); + } + } } + icon={ captionIcon } + isPressed={ showCaption } + label={ + showCaption + ? __( 'Remove caption' ) + : __( 'Add caption' ) + } + /> + ) } + { +export const Gallery = ( props, captionRef ) => { const { attributes, isSelected, @@ -24,6 +24,7 @@ export const Gallery = ( props ) => { insertBlocksAfter, blockProps, __unstableLayoutClassNames: layoutClassNames, + showCaption, } = props; const { align, columns, caption, imageCrop } = attributes; @@ -49,50 +50,32 @@ export const Gallery = ( props ) => { { mediaPlaceholder } ) } - + setAttributes( { caption: value } ) + } + inlineToolbar + __unstableOnSplitAtEnd={ () => + insertBlocksAfter( + createBlock( getDefaultBlockName() ) + ) + } + /> ) } - aria-label={ __( 'Gallery caption text' ) } - placeholder={ __( 'Write gallery caption…' ) } - value={ caption } - onChange={ ( value ) => setAttributes( { caption: value } ) } - inlineToolbar - __unstableOnSplitAtEnd={ () => - insertBlocksAfter( createBlock( getDefaultBlockName() ) ) - } - /> ); }; -function RichTextVisibilityHelper( { - isHidden, - className, - value, - placeholder, - tagName, - captionRef, - ...richTextProps -} ) { - if ( isHidden ) { - return ; - } - - return ( - - ); -} - -export default Gallery; +export default forwardRef( Gallery ); diff --git a/test/e2e/specs/editor/blocks/gallery.spec.js b/test/e2e/specs/editor/blocks/gallery.spec.js index 936942c9688fa5..3881c31d5b8601 100644 --- a/test/e2e/specs/editor/blocks/gallery.spec.js +++ b/test/e2e/specs/editor/blocks/gallery.spec.js @@ -136,12 +136,12 @@ test.describe( 'Gallery', () => { await expect( gallery ).toBeVisible(); await editor.selectBlocks( gallery ); + await editor.clickBlockToolbarButton( 'Add caption' ); const caption = gallery.locator( 'role=textbox[name="Gallery caption text"i]' ); - await expect( caption ).toBeVisible(); - await caption.click(); + await expect( caption ).toBeFocused(); await page.keyboard.type( galleryCaption );