diff --git a/packages/block-library/src/image/image.js b/packages/block-library/src/image/image.js
index 89bf31f92664b..3118f8009a30c 100644
--- a/packages/block-library/src/image/image.js
+++ b/packages/block-library/src/image/image.js
@@ -15,8 +15,11 @@ import {
__experimentalToolsPanelItem as ToolsPanelItem,
__experimentalUseCustomUnits as useCustomUnits,
Placeholder,
+ MenuItem,
+ ToolbarItem,
+ DropdownMenu,
} from '@wordpress/components';
-import { useViewportMatch } from '@wordpress/compose';
+import { useViewportMatch, usePrevious } from '@wordpress/compose';
import { useSelect, useDispatch } from '@wordpress/data';
import {
BlockControls,
@@ -35,7 +38,7 @@ import { __, _x, sprintf, isRTL } from '@wordpress/i18n';
import { DOWN } from '@wordpress/keycodes';
import { getFilename } from '@wordpress/url';
import { getBlockBindingsSource, switchToBlockType } from '@wordpress/blocks';
-import { crop, overlayText, upload } from '@wordpress/icons';
+import { crop, overlayText, upload, chevronDown } from '@wordpress/icons';
import { store as noticesStore } from '@wordpress/notices';
import { store as coreStore } from '@wordpress/core-data';
@@ -69,6 +72,11 @@ const scaleOptions = [
},
];
+const WRITEMODE_POPOVER_PROPS = {
+ placement: 'bottom-start',
+};
+const WRITEMODE_CONTROLS_POPOVER_PROPS = { position: 'bottom right' };
+
// If the image has a href, wrap in an tag to trigger any inherited link element styles.
const ImageWrapper = ( { href, children } ) => {
if ( ! href ) {
@@ -94,6 +102,216 @@ const ImageWrapper = ( { href, children } ) => {
);
};
+function ContentOnlyControls( {
+ attributes,
+ setAttributes,
+ isContentOnlyMode,
+ lockAltControls,
+ lockAltControlsMessage,
+ lockTitleControls,
+ lockTitleControlsMessage,
+} ) {
+ const attributesToDisplayControls = [ 'alt', 'title' ];
+ const [ activeControls, setActiveControls ] = useState( () =>
+ attributesToDisplayControls.filter( ( key ) => {
+ return !! attributes[ key ];
+ } )
+ );
+ const previousActiveControls = usePrevious( activeControls );
+ if ( ! isContentOnlyMode ) {
+ return null;
+ }
+
+ // Display controls in toolbar only if they have a value set or were selected from the dropdown.
+ let controls;
+ if ( !! activeControls.length ) {
+ controls = (
+
+ { activeControls.includes( 'alt' ) && (
+ (
+ {
+ if ( ! isOpen && event.keyCode === DOWN ) {
+ event.preventDefault();
+ onToggle();
+ }
+ } }
+ >
+ { _x(
+ 'Alternative text',
+ 'Alternative text for an image. Block toolbar label, a low character count is preferred.'
+ ) }
+
+ ) }
+ renderContent={ () => (
+
+ setAttributes( { alt: value } )
+ }
+ disabled={ lockAltControls }
+ help={
+ lockAltControls ? (
+ <>{ lockAltControlsMessage }>
+ ) : (
+ <>
+
+ { __(
+ 'Describe the purpose of the image.'
+ ) }
+
+
+ { __(
+ 'Leave empty if decorative.'
+ ) }
+ >
+ )
+ }
+ __nextHasNoMarginBottom
+ />
+ ) }
+ />
+ ) }
+ { activeControls.includes( 'title' ) && (
+ (
+ {
+ if ( ! isOpen && event.keyCode === DOWN ) {
+ event.preventDefault();
+ onToggle();
+ }
+ } }
+ >
+ { __( 'Title' ) }
+
+ ) }
+ renderContent={ () => (
+
+ setAttributes( { title: value } )
+ }
+ disabled={ lockTitleControls }
+ help={
+ lockTitleControls ? (
+ <>{ lockTitleControlsMessage }>
+ ) : (
+ <>
+ { __(
+ 'Describe the role of this image on the page.'
+ ) }
+
+ { __(
+ '(Note: many devices and browsers do not display this text.)'
+ ) }
+
+ >
+ )
+ }
+ />
+ ) }
+ />
+ ) }
+
+ );
+ }
+
+ return (
+ // Add some extra controls for content attributes when content only mode is active.
+ // With content only mode active, the inspector is hidden, so users need another way
+ // to edit these attributes.
+ <>
+ { controls }
+
+
+ { ( toggleProps ) => (
+
+ { ( { onClose } ) => (
+ <>
+
+
+ >
+ ) }
+
+ ) }
+
+
+ >
+ );
+}
+
export default function Image( {
temporaryURL,
attributes,
@@ -621,118 +839,15 @@ export default function Image( {
) }
- { isContentOnlyMode && (
- // Add some extra controls for content attributes when content only mode is active.
- // With content only mode active, the inspector is hidden, so users need another way
- // to edit these attributes.
-
- (
- {
- if ( ! isOpen && event.keyCode === DOWN ) {
- event.preventDefault();
- onToggle();
- }
- } }
- >
- { _x(
- 'Alternative text',
- 'Alternative text for an image. Block toolbar label, a low character count is preferred.'
- ) }
-
- ) }
- renderContent={ () => (
- { lockAltControlsMessage }>
- ) : (
- <>
-
- { __(
- 'Describe the purpose of the image.'
- ) }
-
-
- { __(
- 'Leave empty if decorative.'
- ) }
- >
- )
- }
- __nextHasNoMarginBottom
- />
- ) }
- />
- { title && (
- (
- {
- if (
- ! isOpen &&
- event.keyCode === DOWN
- ) {
- event.preventDefault();
- onToggle();
- }
- } }
- >
- { __( 'Title' ) }
-
- ) }
- renderContent={ () => (
- { lockTitleControlsMessage }>
- ) : (
- <>
- { __(
- 'Describe the role of this image on the page.'
- ) }
-
- { __(
- '(Note: many devices and browsers do not display this text.)'
- ) }
-
- >
- )
- }
- />
- ) }
- />
- ) }
-
- ) }
+