diff --git a/packages/block-library/src/gallery/gallery.js b/packages/block-library/src/gallery/gallery.js
index 0b506cba7fcfb..4a37a203499af 100644
--- a/packages/block-library/src/gallery/gallery.js
+++ b/packages/block-library/src/gallery/gallery.js
@@ -11,6 +11,12 @@ import {
__experimentalUseInnerBlocksProps as useInnerBlocksProps,
} from '@wordpress/block-editor';
import { VisuallyHidden } from '@wordpress/components';
+import {
+ useState,
+ useEffect,
+ useRef,
+ useLayoutEffect,
+} from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import { createBlock } from '@wordpress/blocks';
@@ -46,6 +52,30 @@ export const Gallery = ( props ) => {
__experimentalLayout: { type: 'default', alignments: [] },
} );
+ const [ captionFocused, setCaptionFocused ] = useState( false );
+
+ const captionRef = useRef();
+
+ // Need to use a layout effect here as we can't focus the RichText element
+ // until the DOM render cycle is finished.
+ useLayoutEffect( () => {
+ if ( captionFocused && captionRef.current ) {
+ captionRef.current.focus();
+ }
+ }, [ captionFocused ] );
+
+ function onFocusCaption() {
+ if ( ! captionFocused ) {
+ setCaptionFocused( true );
+ }
+ }
+
+ useEffect( () => {
+ if ( ! isSelected ) {
+ setCaptionFocused( false );
+ }
+ }, [ isSelected ] );
+
return (
);
};
-function RichTextVisibilityHelper( { isHidden, ...richTextProps } ) {
- return isHidden ? (
-
- ) : (
-
+function RichTextVisibilityHelper( {
+ isHidden,
+ captionFocused,
+ onFocusCaption,
+ className,
+ value,
+ placeholder,
+ tagName,
+ captionRef,
+ ...richTextProps
+} ) {
+ if ( isHidden ) {
+ return ;
+ }
+
+ if ( captionFocused ) {
+ return (
+
+ );
+ }
+
+ return (
+
+ { RichText.isEmpty( value ) ? placeholder : value }
+
);
}
diff --git a/packages/block-library/src/gallery/style.scss b/packages/block-library/src/gallery/style.scss
index daa043e3e89cc..4b84b31576a1b 100644
--- a/packages/block-library/src/gallery/style.scss
+++ b/packages/block-library/src/gallery/style.scss
@@ -103,6 +103,7 @@
figcaption {
flex-grow: 1;
flex-basis: 100%;
+ text-align: center;
}
// Non cropped images.