Commit bae680d073 for woocommerce

commit bae680d073e9650545e113dd8b87098f9ad566ed
Author: Karol Manijak <20098064+kmanijak@users.noreply.github.com>
Date:   Fri Apr 25 17:27:10 2025 +0200

    Product Gallery: Add alignment and layout options to Next/Previous buttons (#57484)

    * Add support for alignment, layout and margin

    * Adjust styles

    * Handle alignment in editor

    * Adjust frontend to changes

    * Change the spread of properties so actual buttons are the block and container is just used for alignment

    * Provide alignment to container on frontend

    * Improve type and add some context

    * Add changelog

    * Remove local radius style so theme has more freedom

    * Add experimental selector for global styles

    * Add z-index for editor pseudo-elements to work correctly

    * Pass blockProps to container but provide proper classNames and styles to buttons

    * Refactor class split into more robust and future proof version filtering out local styles classes

    * Add comment with some context

    * Fix outline that may be cut off when buttons are too close

    * Exclude alignment styles from buttons

    * Skip serialization of supports properties so we don't need to filter the properties out from container classnames

    * Fix lint

    * Remove unnecessary z-index preventing from image interactions

    * Fix Next/Prev buttons selector

    ---------

    Co-authored-by: Vladimir Reznichenko <kalessil@gmail.com>

diff --git a/plugins/woocommerce/changelog/wooplug-3913-product-gallery-add-alignment-and-justification-options-to b/plugins/woocommerce/changelog/wooplug-3913-product-gallery-add-alignment-and-justification-options-to
new file mode 100644
index 0000000000..49fcbc3f7a
--- /dev/null
+++ b/plugins/woocommerce/changelog/wooplug-3913-product-gallery-add-alignment-and-justification-options-to
@@ -0,0 +1,4 @@
+Significance: minor
+Type: add
+
+Product Gallery: add alignment options to Next/Prev buttons
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/product-gallery/edit.tsx b/plugins/woocommerce/client/blocks/assets/js/blocks/product-gallery/edit.tsx
index caec0fa6ae..ec1073cf6d 100644
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/product-gallery/edit.tsx
+++ b/plugins/woocommerce/client/blocks/assets/js/blocks/product-gallery/edit.tsx
@@ -28,14 +28,7 @@ const TEMPLATE: InnerBlockTemplate[] = [
 					align: 'right',
 				},
 			],
-			[
-				'woocommerce/product-gallery-large-image-next-previous',
-				{
-					style: {
-						border: { radius: '100%' },
-					},
-				},
-			],
+			[ 'woocommerce/product-gallery-large-image-next-previous' ],
 		],
 	],
 ];
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/product-gallery/inner-blocks/product-gallery-next-previous-buttons/block.json b/plugins/woocommerce/client/blocks/assets/js/blocks/product-gallery/inner-blocks/product-gallery-next-previous-buttons/block.json
index 47e520f8f9..11545356be 100644
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/product-gallery/inner-blocks/product-gallery-next-previous-buttons/block.json
+++ b/plugins/woocommerce/client/blocks/assets/js/blocks/product-gallery/inner-blocks/product-gallery-next-previous-buttons/block.json
@@ -12,12 +12,30 @@
 		"interactivity": true,
 		"color": {
 			"background": true,
-			"text": true
+			"text": true,
+			"__experimentalSkipSerialization": true
+		},
+		"align": true,
+		"layout": {
+			"default": {
+				"type": "flex",
+				"flexWrap": "nowrap",
+				"verticalAlignment": "center"
+			},
+			"allowVerticalAlignment": true,
+			"allowOrientation": false,
+			"allowJustification": false
 		},
 		"shadow": true,
+		"spacing": {
+			"margin": true,
+			"__experimentalSkipSerialization": true
+		},
 		"__experimentalBorder": {
-			"radius": true
-		}
+			"radius": true,
+			"__experimentalSkipSerialization": true
+		},
+		"__experimentalSelector": ".wc-block-product-gallery-large-image-next-previous__button"
 	},
 	"ancestor": [ "woocommerce/product-gallery-large-image" ]
 }
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/product-gallery/inner-blocks/product-gallery-next-previous-buttons/edit.tsx b/plugins/woocommerce/client/blocks/assets/js/blocks/product-gallery/inner-blocks/product-gallery-next-previous-buttons/edit.tsx
index 418f3138a2..7328421058 100644
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/product-gallery/inner-blocks/product-gallery-next-previous-buttons/edit.tsx
+++ b/plugins/woocommerce/client/blocks/assets/js/blocks/product-gallery/inner-blocks/product-gallery-next-previous-buttons/edit.tsx
@@ -1,24 +1,80 @@
 /**
  * External dependencies
  */
-import { useBlockProps } from '@wordpress/block-editor';
+import type { BlockAttributes } from '@wordpress/blocks';
+import clsx from 'clsx';
+import {
+	useBlockProps,
+	/* eslint-disable */
+	/* @ts-ignore module is exported as experimental */
+	__experimentalUseBorderProps as useBorderProps,
+	/* @ts-ignore module is exported as experimental */
+	__experimentalUseColorProps as useColorProps,
+	/* @ts-ignore module is exported as experimental */
+	__experimentalGetSpacingClassesAndStyles as useSpacingProps,
+	/* @ts-ignore module is exported as experimental */
+	__experimentalGetShadowClassesAndStyles as useShadowProps,
+	/* eslint-enable */
+} from '@wordpress/block-editor';

 /**
  * Internal dependencies
  */
 import { PrevIcon, NextIcon } from './icons';

-export const Edit = (): JSX.Element => {
-	const blockProps = useBlockProps( {
-		className: 'wc-block-product-gallery-large-image-next-previous__button',
+const getVerticalAlignmentClass = ( attributes: BlockAttributes ) => {
+	const verticalAlignment = attributes?.layout?.verticalAlignment;
+
+	if ( verticalAlignment === 'top' ) {
+		return 'aligntop';
+	}
+	if ( verticalAlignment === 'bottom' ) {
+		return 'alignbottom';
+	}
+	// Default to center.
+	return '';
+};
+
+export const Edit = ( { attributes }: { attributes: BlockAttributes } ) => {
+	const verticalAlignmentClass = getVerticalAlignmentClass( attributes );
+	const { style, ...blockProps } = useBlockProps( {
+		className: clsx(
+			'wc-block-product-gallery-large-image-next-previous',
+			verticalAlignmentClass
+		),
 	} );

+	const borderProps = useBorderProps( attributes );
+	const colorProps = useColorProps( attributes );
+	const spacingProps = useSpacingProps( attributes );
+	const shadowProps = useShadowProps( attributes );
+
+	const buttonClassName = clsx(
+		'wc-block-product-gallery-large-image-next-previous__button',
+		borderProps.className,
+		colorProps.className,
+		spacingProps.className,
+		shadowProps.className
+	);
+
+	const buttonStyles = {
+		...style,
+		...borderProps.style,
+		...colorProps.style,
+		...spacingProps.style,
+		...shadowProps.style,
+	};
+
 	return (
-		<div className="wc-block-product-gallery-large-image-next-previous">
-			<button { ...blockProps } disabled>
+		<div { ...blockProps }>
+			<button
+				className={ buttonClassName }
+				style={ buttonStyles }
+				disabled
+			>
 				<PrevIcon className="wc-block-product-gallery-large-image-next-previous__icon wc-block-product-gallery-large-image-next-previous__icon--left" />
 			</button>
-			<button { ...blockProps }>
+			<button className={ buttonClassName } style={ buttonStyles }>
 				<NextIcon className="wc-block-product-gallery-large-image-next-previous__icon wc-block-product-gallery-large-image-next-previous__icon--right" />
 			</button>
 		</div>
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/product-gallery/style.scss b/plugins/woocommerce/client/blocks/assets/js/blocks/product-gallery/style.scss
index 64ec44b446..08b0027625 100644
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/product-gallery/style.scss
+++ b/plugins/woocommerce/client/blocks/assets/js/blocks/product-gallery/style.scss
@@ -106,14 +106,38 @@ $dialog-padding: 20px;
 		font-size: 12px;
 		padding: 0;
 		background: #fff;
+		outline-offset: -2px;

 		&:disabled {
 			.wc-block-product-gallery-large-image-next-previous__icon {
-				opacity: 35%;
+				opacity: 30%;
 			}
 			cursor: not-allowed;
 		}
 	}
+
+	&.alignleft {
+		justify-content: flex-start;
+		gap: 0;
+	}
+
+	&.alignright {
+		justify-content: flex-end;
+		gap: 0;
+	}
+
+	&.aligncenter {
+		justify-content: center;
+		gap: 0;
+	}
+
+	&.aligntop {
+		align-items: flex-start;
+	}
+
+	&.alignbottom {
+		align-items: flex-end;
+	}
 }

 @mixin vertical-thumbnails {
diff --git a/plugins/woocommerce/client/blocks/tests/e2e/tests/product-gallery/inner-blocks/product-gallery-large-image-next-previous/product-gallery-large-image-next-previous.block_theme.spec.ts b/plugins/woocommerce/client/blocks/tests/e2e/tests/product-gallery/inner-blocks/product-gallery-large-image-next-previous/product-gallery-large-image-next-previous.block_theme.spec.ts
index 4ec5f214d7..f545377ef1 100644
--- a/plugins/woocommerce/client/blocks/tests/e2e/tests/product-gallery/inner-blocks/product-gallery-large-image-next-previous/product-gallery-large-image-next-previous.block_theme.spec.ts
+++ b/plugins/woocommerce/client/blocks/tests/e2e/tests/product-gallery/inner-blocks/product-gallery-large-image-next-previous/product-gallery-large-image-next-previous.block_theme.spec.ts
@@ -89,13 +89,11 @@ test.describe( `${ blockData.name }`, () => {
 			name: 'woocommerce/product-gallery',
 		} );

-		const blocks = await pageObject.getNextPreviousButtonsBlock( {
+		const block = await pageObject.getNextPreviousButtonsBlock( {
 			page: 'editor',
 		} );

-		// There are two "instances" of the block in the editor, so we need to check both.
-		await expect( blocks.nth( 0 ) ).toBeVisible();
-		await expect( blocks.nth( 1 ) ).toBeVisible();
+		await expect( block ).toBeVisible();
 	} );

 	test( 'Renders Next/Previous Button block on the frontend side', async ( {
diff --git a/plugins/woocommerce/src/Blocks/BlockTypes/ProductGalleryLargeImageNextPrevious.php b/plugins/woocommerce/src/Blocks/BlockTypes/ProductGalleryLargeImageNextPrevious.php
index ba80644b36..595c0a0922 100644
--- a/plugins/woocommerce/src/Blocks/BlockTypes/ProductGalleryLargeImageNextPrevious.php
+++ b/plugins/woocommerce/src/Blocks/BlockTypes/ProductGalleryLargeImageNextPrevious.php
@@ -59,12 +59,13 @@ class ProductGalleryLargeImageNextPrevious extends AbstractBlock {
 			return '';
 		}

-		$classes_and_styles = StyleAttributesUtils::get_classes_and_styles_by_attributes( $attributes );
+		$classes_and_styles = StyleAttributesUtils::get_classes_and_styles_by_attributes( $attributes, array(), array( 'align' ) );
+		$vertical_alignment = StyleAttributesUtils::get_align_class_and_style( $attributes );

 		ob_start();
 		?>
 		<div
-			class="wc-block-product-gallery-large-image-next-previous"
+			class="wc-block-product-gallery-large-image-next-previous <?php echo esc_attr( $vertical_alignment['class'] ); ?>"
 			data-wp-interactive="woocommerce/product-gallery"
 		>
 			<button