Update ImageGallery toolbar: changing icon to text and adding ellipsis menu (#39753)
* Update ImageGallery Toolbar by adding an ellipsis options dropdown menu * Add changelog * Remove typings * Fix build issues * Fix lint errors * Add comment and remove old comment
This commit is contained in:
parent
278366def9
commit
b3f7be5fdc
|
@ -0,0 +1,4 @@
|
|||
Significance: minor
|
||||
Type: update
|
||||
|
||||
Update ImageGallery block toolbar, moving some options to an ellipsis dropdown menu.
|
|
@ -1,6 +1,6 @@
|
|||
.woocommerce-image-gallery__item {
|
||||
height: 146px;
|
||||
width: 146px;
|
||||
height: 146px;
|
||||
width: 146px;
|
||||
position: relative;
|
||||
|
||||
&.is-toolbar-visible {
|
||||
|
@ -9,40 +9,38 @@
|
|||
}
|
||||
}
|
||||
|
||||
&:not(.is-toolbar-visible){
|
||||
&:not(.is-toolbar-visible) {
|
||||
img:hover {
|
||||
border: 1.5px solid #007cba;
|
||||
}
|
||||
}
|
||||
|
||||
img {
|
||||
img {
|
||||
border: 1px solid $gray-200;
|
||||
border-radius: 3px;
|
||||
box-sizing: border-box;
|
||||
object-fit: cover;
|
||||
width: 100%;
|
||||
height: 146px;
|
||||
}
|
||||
}
|
||||
|
||||
.woocommerce-pill {
|
||||
background: var(--wp-admin-theme-color);
|
||||
border: 0;
|
||||
color: $white;
|
||||
padding-top: 2px;
|
||||
padding-bottom: 2px;
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
left: 10px;
|
||||
}
|
||||
.woocommerce-pill {
|
||||
background: var(--wp-admin-theme-color);
|
||||
border: 0;
|
||||
color: $white;
|
||||
padding-top: 2px;
|
||||
padding-bottom: 2px;
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
left: 10px;
|
||||
}
|
||||
|
||||
.components-toolbar-group {
|
||||
flex-wrap: inherit;
|
||||
border-right: 1px solid #ccc;
|
||||
|
||||
svg {
|
||||
width: 24px;
|
||||
margin-top: $gap-smallest;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
// Hack to hide when the media modal is open
|
||||
// Otherwise in Firefox the popover remains visible on top of the modal
|
||||
// Changing the z-index of Popovers have wider implications.
|
||||
.modal-open .woocommerce-image-gallery__toolbar-dropdown-popover {
|
||||
display: none;
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { DropdownMenu, MenuGroup, MenuItem } from '@wordpress/components';
|
||||
import { moreVertical } from '@wordpress/icons';
|
||||
import {
|
||||
Children,
|
||||
cloneElement,
|
||||
createElement,
|
||||
Fragment,
|
||||
isValidElement,
|
||||
} from '@wordpress/element';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { MediaItem, MediaUpload } from '@wordpress/media-utils';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { MediaUploadComponentType } from './types';
|
||||
|
||||
const POPOVER_PROPS = {
|
||||
className: 'woocommerce-image-gallery__toolbar-dropdown-popover',
|
||||
placement: 'bottom-start',
|
||||
};
|
||||
|
||||
type ImageGalleryToolbarDropdownProps = {
|
||||
onReplace: ( media: { id: number } & MediaItem ) => void;
|
||||
onRemove: () => void;
|
||||
canRemove?: boolean;
|
||||
removeBlockLabel?: string;
|
||||
MediaUploadComponent: MediaUploadComponentType;
|
||||
};
|
||||
|
||||
export function ImageGalleryToolbarDropdown( {
|
||||
children,
|
||||
onReplace,
|
||||
onRemove,
|
||||
canRemove,
|
||||
removeBlockLabel,
|
||||
MediaUploadComponent = MediaUpload,
|
||||
...props
|
||||
}: React.PropsWithChildren< ImageGalleryToolbarDropdownProps > ) {
|
||||
return (
|
||||
<DropdownMenu
|
||||
icon={ moreVertical }
|
||||
label={ __( 'Options', 'woocommerce' ) }
|
||||
className="woocommerce-image-gallery__toolbar-dropdown"
|
||||
popoverProps={ POPOVER_PROPS }
|
||||
{ ...props }
|
||||
>
|
||||
{ ( { onClose } ) => (
|
||||
<>
|
||||
<MenuGroup>
|
||||
<MediaUploadComponent
|
||||
onSelect={ ( media ) => {
|
||||
onReplace( media as MediaItem );
|
||||
onClose();
|
||||
} }
|
||||
allowedTypes={ [ 'image' ] }
|
||||
render={ ( { open } ) => (
|
||||
<MenuItem
|
||||
onClick={ () => {
|
||||
open();
|
||||
} }
|
||||
>
|
||||
{ __( 'Replace', 'woocommerce' ) }
|
||||
</MenuItem>
|
||||
) }
|
||||
/>
|
||||
</MenuGroup>
|
||||
{ typeof children === 'function'
|
||||
? children( { onClose } )
|
||||
: Children.map(
|
||||
children,
|
||||
( child ) =>
|
||||
isValidElement< { onClose: () => void } >(
|
||||
child
|
||||
) &&
|
||||
cloneElement< { onClose: () => void } >(
|
||||
child,
|
||||
{ onClose }
|
||||
)
|
||||
) }
|
||||
{ canRemove && (
|
||||
<MenuGroup>
|
||||
<MenuItem
|
||||
onClick={ () => {
|
||||
onClose();
|
||||
onRemove();
|
||||
} }
|
||||
>
|
||||
{ removeBlockLabel ||
|
||||
__( 'Remove', 'woocommerce' ) }
|
||||
</MenuItem>
|
||||
</MenuGroup>
|
||||
) }
|
||||
</>
|
||||
) }
|
||||
</DropdownMenu>
|
||||
);
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
.woocommerce-image-gallery__toolbar {
|
||||
width: max-content;
|
||||
position: absolute;
|
||||
top: -58px;
|
||||
left: 50%;
|
||||
|
|
|
@ -2,17 +2,25 @@
|
|||
* External dependencies
|
||||
*/
|
||||
import { createElement } from '@wordpress/element';
|
||||
import { Toolbar, ToolbarButton, ToolbarGroup } from '@wordpress/components';
|
||||
import { chevronRight, chevronLeft, trash } from '@wordpress/icons';
|
||||
import { MediaItem, MediaUpload } from '@wordpress/media-utils';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import {
|
||||
Toolbar,
|
||||
ToolbarButton,
|
||||
ToolbarGroup,
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore No types for this exist yet.
|
||||
// eslint-disable-next-line @woocommerce/dependency-group
|
||||
ToolbarItem,
|
||||
} from '@wordpress/components';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { CoverImageIcon } from './icons';
|
||||
import { SortableHandle } from '../sortable';
|
||||
import { MediaUploadComponentType } from './types';
|
||||
import { ImageGalleryToolbarDropdown } from './image-gallery-toolbar-dropdown';
|
||||
|
||||
export type ImageGalleryToolbarProps = {
|
||||
childIndex: number;
|
||||
|
@ -88,31 +96,60 @@ export const ImageGalleryToolbar: React.FC< ImageGalleryToolbarProps > = ( {
|
|||
<ToolbarGroup>
|
||||
<ToolbarButton
|
||||
onClick={ () => setAsCoverImage( childIndex ) }
|
||||
icon={ CoverImageIcon }
|
||||
label={ __( 'Set as cover', 'woocommerce' ) }
|
||||
>
|
||||
{ __( 'Set as cover', 'woocommerce' ) }
|
||||
</ToolbarButton>
|
||||
</ToolbarGroup>
|
||||
) }
|
||||
{ isCoverItem && (
|
||||
<ToolbarGroup className="woocommerce-image-gallery__toolbar-media">
|
||||
<MediaUploadComponent
|
||||
onSelect={ ( media ) =>
|
||||
replaceItem( childIndex, media as MediaItem )
|
||||
}
|
||||
allowedTypes={ [ 'image' ] }
|
||||
render={ ( { open } ) => (
|
||||
<ToolbarButton onClick={ open }>
|
||||
{ __( 'Replace', 'woocommerce' ) }
|
||||
</ToolbarButton>
|
||||
) }
|
||||
/>
|
||||
</ToolbarGroup>
|
||||
) }
|
||||
<ToolbarGroup className="woocommerce-image-gallery__toolbar-media">
|
||||
<MediaUploadComponent
|
||||
onSelect={ ( media ) =>
|
||||
replaceItem( childIndex, media as MediaItem )
|
||||
}
|
||||
allowedTypes={ [ 'image' ] }
|
||||
render={ ( { open } ) => (
|
||||
<ToolbarButton onClick={ open }>
|
||||
{ __( 'Replace', 'woocommerce' ) }
|
||||
</ToolbarButton>
|
||||
) }
|
||||
/>
|
||||
</ToolbarGroup>
|
||||
<ToolbarGroup>
|
||||
<ToolbarButton
|
||||
onClick={ () => removeItem( childIndex ) }
|
||||
icon={ trash }
|
||||
label={ __( 'Remove', 'woocommerce' ) }
|
||||
/>
|
||||
</ToolbarGroup>
|
||||
{ isCoverItem && (
|
||||
<ToolbarGroup>
|
||||
<ToolbarButton
|
||||
onClick={ () => removeItem( childIndex ) }
|
||||
icon={ trash }
|
||||
label={ __( 'Remove', 'woocommerce' ) }
|
||||
/>
|
||||
</ToolbarGroup>
|
||||
) }
|
||||
{ ! isCoverItem && (
|
||||
<ToolbarGroup>
|
||||
<ToolbarItem>
|
||||
{ ( toggleProps: {
|
||||
'data-toolbar-item': boolean;
|
||||
ref: React.ForwardedRef<
|
||||
typeof ImageGalleryToolbarDropdown
|
||||
>;
|
||||
} ) => (
|
||||
<ImageGalleryToolbarDropdown
|
||||
canRemove={ true }
|
||||
onRemove={ () => removeItem( childIndex ) }
|
||||
onReplace={ ( media ) =>
|
||||
replaceItem( childIndex, media )
|
||||
}
|
||||
MediaUploadComponent={
|
||||
MediaUploadComponent
|
||||
}
|
||||
{ ...toggleProps }
|
||||
/>
|
||||
) }
|
||||
</ToolbarItem>
|
||||
</ToolbarGroup>
|
||||
) }
|
||||
</Toolbar>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -129,6 +129,20 @@ export const ImageGallery: React.FC< ImageGalleryProps > = ( {
|
|||
event.relatedTarget as Element
|
||||
).closest(
|
||||
'.media-modal, .components-modal__frame'
|
||||
) ) ||
|
||||
( event.relatedTarget &&
|
||||
// Check if not a button within the toolbar is clicked, to prevent hiding the toolbar.
|
||||
(
|
||||
event.relatedTarget as Element
|
||||
).closest(
|
||||
'.woocommerce-image-gallery__toolbar'
|
||||
) ) ||
|
||||
( event.relatedTarget &&
|
||||
// Prevent toolbar from hiding if the dropdown is clicked within the toolbar.
|
||||
(
|
||||
event.relatedTarget as Element
|
||||
).closest(
|
||||
'.woocommerce-image-gallery__toolbar-dropdown-popover'
|
||||
) )
|
||||
) {
|
||||
return;
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
@import 'image-gallery.scss';
|
||||
@import 'image-gallery-item.scss';
|
||||
@import 'image-gallery-toolbar.scss';
|
||||
@import "image-gallery.scss";
|
||||
@import "image-gallery-item.scss";
|
||||
@import "image-gallery-toolbar.scss";
|
||||
@import "image-gallery-toolbar-dropdown.scss";
|
||||
|
|
Loading…
Reference in New Issue