From 0a93c24c0633f83021ef359860ee7fa73fc10e8c Mon Sep 17 00:00:00 2001 From: ntsekouras Date: Wed, 30 Oct 2024 16:54:39 +0200 Subject: [PATCH] Image block: Add support for "more" dropdown for additional tools in Write mode --- packages/block-library/src/image/image.js | 343 +++++++++++++++------- 1 file changed, 229 insertions(+), 114 deletions(-) diff --git a/packages/block-library/src/image/image.js b/packages/block-library/src/image/image.js index 89bf31f92664b9..3118f8009a30c1 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 } ) => ( + <> + { + setActiveControls( ( prev ) => [ + ...prev, + 'alt', + ] ); + onClose(); + } } + disabled={ activeControls.includes( + 'alt' + ) } + > + { _x( + 'Alternative text', + 'Alternative text for an image. Block toolbar label, a low character count is preferred.' + ) } + + { + setActiveControls( ( prev ) => [ + ...prev, + 'title', + ] ); + onClose(); + } } + disabled={ activeControls.includes( + 'title' + ) } + > + { __( 'Title text' ) } + + + ) } + + ) } + + + + ); +} + 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.)' - ) } - - - ) - } - /> - ) } - /> - ) } -
- ) } +