@@ -22,6 +22,8 @@ import {
2222 __experimentalItemGroup as ItemGroup ,
2323 __experimentalHStack as HStack ,
2424 __experimentalTruncate as Truncate ,
25+ Dropdown ,
26+ __experimentalDropdownContentWrapper as DropdownContentWrapper ,
2527} from '@wordpress/components' ;
2628import { __ , sprintf } from '@wordpress/i18n' ;
2729import { store as noticesStore } from '@wordpress/notices' ;
@@ -30,6 +32,7 @@ import { useCallback, Platform, useRef } from '@wordpress/element';
3032import { useDispatch , useSelect } from '@wordpress/data' ;
3133import { focus } from '@wordpress/dom' ;
3234import { isBlobURL } from '@wordpress/blob' ;
35+ import { reusableBlock , Icon , chevronRight } from '@wordpress/icons' ;
3336
3437/**
3538 * Internal dependencies
@@ -134,48 +137,120 @@ export const backgroundPositionToCoords = ( value ) => {
134137 return { x, y } ;
135138} ;
136139
137- function InspectorImagePreview ( { label, filename, url : imgUrl } ) {
140+
141+ const popoverProps = {
142+ placement : 'left-start' ,
143+ offset : 36 ,
144+ shift : true ,
145+ }
146+ function InspectorImagePreview ( { label, filename, url : imgUrl , children, allowPopover = false } ) {
138147 const imgLabel = label || getFilename ( imgUrl ) ;
139- return (
140- < ItemGroup as = "span" >
141- < HStack justify = "flex-start" as = "span" >
142- < span
143- className = { classnames (
144- 'block-editor-global-styles-background-panel__inspector-image-indicator-wrapper' ,
145- {
146- 'has-image' : imgUrl ,
147- }
148- ) }
149- aria-hidden
150- >
151- { imgUrl && (
152- < span
153- className = "block-editor-global-styles-background-panel__inspector-image-indicator"
154- style = { {
155- backgroundImage : `url(${ imgUrl } )` ,
156- } }
157- />
158- ) }
159- </ span >
160- < FlexItem as = "span" >
161- < Truncate
162- numberOfLines = { 1 }
163- className = "block-editor-global-styles-background-panel__inspector-media-replace-title"
148+ // @TODO abstract
149+ if ( ! allowPopover ) {
150+ return (
151+ < ItemGroup as = "span" className = "block-editor-global-styles-background-panel__image-preview" >
152+ < HStack justify = "flex-start" as = "span" className = "block-editor-global-styles-background-panel__image-preview-content" >
153+ < span
154+ className = { classnames (
155+ 'block-editor-global-styles-background-panel__inspector-image-indicator-wrapper' ,
156+ {
157+ 'has-image' : imgUrl ,
158+ }
159+ ) }
160+ aria-hidden
164161 >
165- { imgLabel }
166- </ Truncate >
167- < VisuallyHidden as = "span" >
168- { filename
169- ? sprintf (
162+ { imgUrl && (
163+ < span
164+ className = "block-editor-global-styles-background-panel__inspector-image-indicator"
165+ style = { {
166+ backgroundImage : `url(${ imgUrl } )` ,
167+ } }
168+ />
169+ ) }
170+ </ span >
171+ < FlexItem as = "span" >
172+ < Truncate
173+ numberOfLines = { 1 }
174+ className = "block-editor-global-styles-background-panel__inspector-media-replace-title"
175+ >
176+ { imgLabel }
177+ </ Truncate >
178+ < VisuallyHidden as = "span" >
179+ { filename
180+ ? sprintf (
170181 /* translators: %s: file name */
171182 __ ( 'Selected image: %s' ) ,
172183 filename
173- )
174- : __ ( 'No image selected' ) }
175- </ VisuallyHidden >
176- </ FlexItem >
177- </ HStack >
178- </ ItemGroup >
184+ )
185+ : __ ( 'No image selected' ) }
186+ </ VisuallyHidden >
187+ </ FlexItem >
188+ </ HStack >
189+ </ ItemGroup >
190+ ) ;
191+ }
192+ return (
193+ < Dropdown
194+ popoverProps = { popoverProps }
195+ className = "block-editor-global-styles-background-panel__inspector-media-replace"
196+ renderToggle = { ( { onToggle, isOpen } ) => {
197+ const toggleProps = {
198+ onClick : onToggle ,
199+ className : classnames (
200+ 'block-editor-global-styles-background-panel__dropdown' ,
201+ { 'is-open' : isOpen }
202+ ) ,
203+ 'aria-expanded' : isOpen ,
204+ 'aria-label' : __ ( 'Background size, position and repeat options.' ) ,
205+ } ;
206+ return (
207+ < ItemGroup as = "button" { ...toggleProps } >
208+ < HStack justify = "flex-start" as = "span" >
209+ < span
210+ className = { classnames (
211+ 'block-editor-global-styles-background-panel__inspector-image-indicator-wrapper' ,
212+ {
213+ 'has-image' : imgUrl ,
214+ }
215+ ) }
216+ aria-hidden
217+ >
218+ { imgUrl && (
219+ < span
220+ className = "block-editor-global-styles-background-panel__inspector-image-indicator"
221+ style = { {
222+ backgroundImage : `url(${ imgUrl } )` ,
223+ } }
224+ />
225+ ) }
226+ </ span >
227+ < FlexItem as = "span" >
228+ < Truncate
229+ numberOfLines = { 1 }
230+ className = "block-editor-global-styles-background-panel__inspector-media-replace-title"
231+ >
232+ { imgLabel }
233+ </ Truncate >
234+ < VisuallyHidden as = "span" >
235+ { filename
236+ ? sprintf (
237+ /* translators: %s: file name */
238+ __ ( 'Selected image: %s' ) ,
239+ filename
240+ )
241+ : __ ( 'No image selected' ) }
242+ </ VisuallyHidden >
243+ </ FlexItem >
244+ </ HStack >
245+ </ ItemGroup >
246+ ) ;
247+ } }
248+ renderContent = { ( { onClose } ) => (
249+ < DropdownContentWrapper >
250+ { children }
251+ </ DropdownContentWrapper >
252+ ) }
253+ />
179254 ) ;
180255}
181256
@@ -185,6 +260,8 @@ function BackgroundImageToolsPanelItem( {
185260 onChange,
186261 style,
187262 inheritedValue,
263+ settings,
264+ defaultControlValues,
188265} ) {
189266 const mediaUpload = useSelect (
190267 ( select ) => select ( blockEditorStore ) . getSettings ( ) . mediaUpload ,
@@ -273,6 +350,8 @@ function BackgroundImageToolsPanelItem( {
273350 hasBackgroundImageValue ( style ) ||
274351 hasBackgroundImageValue ( inheritedValue ) ;
275352
353+ const shouldShowBackgroundSizeControls = hasValue && settings ?. background ?. backgroundSize ;
354+
276355 return (
277356 < ToolsPanelItem
278357 className = "single-column"
@@ -287,20 +366,31 @@ function BackgroundImageToolsPanelItem( {
287366 className = "block-editor-global-styles-background-panel__inspector-media-replace-container"
288367 ref = { replaceContainerRef }
289368 >
369+ < InspectorImagePreview
370+ label = { __ ( 'Background image' ) }
371+ filename = { title || __ ( 'Untitled' ) }
372+ url = { url }
373+ allowPopover = { shouldShowBackgroundSizeControls }
374+ >
375+ < BackgroundSizeToolsPanelItem
376+ onChange = { onChange }
377+ panelId = { panelId }
378+ isShownByDefault = { true }
379+ style = { style }
380+ inheritedValue = { inheritedValue }
381+ defaultControlValues = { defaultControlValues }
382+ />
383+ </ InspectorImagePreview >
290384 < MediaReplaceFlow
291385 mediaId = { id }
292386 mediaURL = { url }
293387 allowedTypes = { [ IMAGE_BACKGROUND_TYPE ] }
294388 accept = "image/*"
295389 onSelect = { onSelectMedia }
390+ variant = "secondary"
296391 name = {
297- < InspectorImagePreview
298- label = { __ ( 'Background image' ) }
299- filename = { title || __ ( 'Untitled' ) }
300- url = { url }
301- />
392+ < Icon icon = { reusableBlock } />
302393 }
303- variant = "secondary"
304394 >
305395 { hasValue && (
306396 < MenuItem
@@ -565,8 +655,6 @@ export default function BackgroundPanel( {
565655 background : { } ,
566656 } ;
567657 } , [ ] ) ;
568- const shouldShowBackgroundSizeControls =
569- settings ?. background ?. backgroundSize ;
570658
571659 return (
572660 < Wrapper
@@ -581,17 +669,9 @@ export default function BackgroundPanel( {
581669 isShownByDefault = { defaultControls . backgroundImage }
582670 style = { value }
583671 inheritedValue = { inheritedValue }
672+ defaultControlValues = { defaultControlValues }
673+ settings = { settings }
584674 />
585- { shouldShowBackgroundSizeControls && (
586- < BackgroundSizeToolsPanelItem
587- onChange = { onChange }
588- panelId = { panelId }
589- isShownByDefault = { defaultControls . backgroundSize }
590- style = { value }
591- inheritedValue = { inheritedValue }
592- defaultControlValues = { defaultControlValues }
593- />
594- ) }
595675 </ Wrapper >
596676 ) ;
597677}
0 commit comments