Repository: Automattic/jetpack
Pull request #43268: Forms: only apply `wp-` and `is-style-` classes to fields of new inner block types
Author: login: ramonjd
Labels: name: [Feature] Forms
name: [Package] Forms
name: [Tests] Includes Tests
Created: 2025-04-28T02:47:52Z | Merged: 2025-04-29T01:28:18Z

## Proposed changes:

Fixes https://github.com/Automattic/jetpack-roadmap/issues/2490

Follow up to https://github.com/Automattic/jetpack/pull/43184

Only apply the block style classes to the field wrapper if the field is one of the new inner block types. See: https://github.com/Automattic/jetpack/pull/43184#discussion_r2057604422

Why? The general approach has been to preserve existing forms on the frontend so that there's not style shock when https://github.com/Automattic/jetpack/pull/42890 is eventually merged.

This PR ensures that we only modify forms that have the new inner blocks introduced in https://github.com/Automattic/jetpack/pull/42890.

Thank you.

- [x] Update test cases




## Testing instructions

Create a form in trunk. Include a multi-option checkbox for example.

Save that form. Let's call it "Your form".

Now checkout this branch, and visit "Your form" on the frontend. 

Using the browser's inspector tool, check the wrapping div of the fields. They should have their regular classnames, e.g., `grunion-field-checkbox-multiple-wrap`, BUT they shouldn't have any WordPress block classes, e.g., `wp-block-jetpack-field-checkbox-multiple`. 

Edit the page with "Your form" and save.

Return to the frontend and refresh.

Now, the fields should have their regular classnames, e.g., `grunion-field-checkbox-multiple-wrap`, AND they the correct WordPress block classes, e.g., `wp-block-jetpack-field-checkbox-multiple`. 

Run the tests!

```
jetpack test php packages/forms --verbose --debug
```


Diff:
diff --git a/projects/packages/forms/src/contact-form/class-contact-form-field.php b/projects/packages/forms/src/contact-form/class-contact-form-field.php
index 9412397429cb..a828b5d8b08d 100644
--- a/projects/packages/forms/src/contact-form/class-contact-form-field.php
+++ b/projects/packages/forms/src/contact-form/class-contact-form-field.php
@@ -1492,13 +1492,13 @@ public function render_field( $type, $id, $label, $value, $class, $placeholder,
 
 		// Shell wrapper classes. Add -wrap to each class.
 		$wrap_classes          = empty( $class ) ? '' : implode( '-wrap ', array_filter( explode( ' ', $class ) ) ) . '-wrap';
-		$field_wrapper_classes = $this->get_attribute( 'fieldwrapperclasses' ) ?? '';
+		$field_wrapper_classes = $this->get_attribute( 'fieldwrapperclasses' ) ? $this->get_attribute( 'fieldwrapperclasses' ) . ' ' : '';
 
 		if ( empty( $label ) ) {
 			$wrap_classes .= ' no-label';
 		}
 
-		$shell_field_class = "class='" . $field_wrapper_classes . ' grunion-field-' . $trimmed_type . '-wrap ' . esc_attr( $wrap_classes ) . "' ";
+		$shell_field_class = "class='" . $field_wrapper_classes . 'grunion-field-' . $trimmed_type . '-wrap ' . esc_attr( $wrap_classes ) . "' ";
 
 		/**
 		 * Filter the Contact Form required field text
diff --git a/projects/packages/forms/src/contact-form/class-contact-form-plugin.php b/projects/packages/forms/src/contact-form/class-contact-form-plugin.php
index 6c9085e0a2ef..eb9d8915c292 100644
--- a/projects/packages/forms/src/contact-form/class-contact-form-plugin.php
+++ b/projects/packages/forms/src/contact-form/class-contact-form-plugin.php
@@ -377,38 +377,41 @@ private static function get_block_support_classes_and_styles( $block_name, $attr
 	}
 
 	/**
-	 * Returns an array containing the block style classes, the remaining classes without block style classes, and the wrap classes.
+	 * Returns an array containing the field classes (including -wrap classes), the remaining classes without block style classes.
 	 * The wrap classes are used for the wrapper div around the field.
 	 *
 	 * @param string $classname The class name.
 	 *
 	 * @return array {
-	 *     @type string $block_style_classes         The block style classes (is-style-* classes).
-	 *     @type string $classes_without_block_style The remaining classes without block style classes.
-	 *     @type string $wrap_classes                The wrap classes.
+	 *     @type string $fieldwrapperclasses         Classes that should be added to the field wrapper.
+	 *     @type string $classes_without_block_style The remaining classes without block style classes, intended for internal field controls.
 	 * }
 	 */
 	private static function get_block_style_classes( $classname = '' ) {
 		if ( ! $classname ) {
 			return array(
-				'block_style_classes' => '',
+				'fieldwrapperclasses' => '',
 				'classes'             => '',
-				'wrap_classes'        => '',
 			);
 		}
 
+		$field_wrapper_classes       = '';
+		$classes_without_block_style = '';
+
 		preg_match_all( '/is-style-([^\s]+)/i', $classname, $matches );
 
 		$block_style_classes = empty( $matches[0] ) ? '' : implode( ' ', $matches[0] );
-		$wrap_classes        = ! empty( $matches[0] ) ? implode( '-wrap ', $matches[0] ) . '-wrap' : '';
 
-		// Remove block style classes from the original classname
-		$classes_without_block_style = trim( preg_replace( '/is-style-([^\s]+)/i', '', $classname ) );
+		if ( ! empty( $block_style_classes ) ) {
+			$wrap_classes          = ! empty( $matches[0] ) ? ' ' . implode( '-wrap ', $matches[0] ) . '-wrap' : '';
+			$field_wrapper_classes = " $block_style_classes $wrap_classes";
+			// Remove block style classes from the original classname.
+			$classes_without_block_style = trim( preg_replace( '/is-style-([^\s]+)/i', '', $classname ) );
+		}
 
 		return array(
-			'block_style_classes' => $block_style_classes,
+			'fieldwrapperclasses' => $field_wrapper_classes,
 			'classes'             => $classes_without_block_style,
-			'wrap_classes'        => $wrap_classes,
 		);
 	}
 
@@ -435,30 +438,20 @@ public static function block_attributes_to_shortcode_attributes( $atts, $type, $
 
 		// Process inner blocks to shortcode attributes.
 		if ( $block && ! empty( $block->parsed_block['innerBlocks'] ) ) {
-			/*
-			 * Add the `wp-block-jetpack-field-*` and `is-style-*` classes to the field wrapper div
-			 * This ensures any updates to field block styles in theme.json or global styles are
-			 * correctly applied.
-			 */
-			$atts['fieldwrapperclasses'] = 'wp-block-jetpack-field-' . $type;
-			if ( ! empty( $atts['class'] ) ) {
-				$block_style_classes          = self::get_block_style_classes( $atts['class'] );
-				$spacer                       = ! empty( $block_style_classes['block_style_classes'] ) ? ' ' : '';
-				$atts['fieldwrapperclasses'] .= $spacer . $block_style_classes['block_style_classes'] . $spacer . $block_style_classes['wrap_classes'];
-				// Return the rest of the classes without the block style classes.
-				$atts['class'] = ! empty( $block_style_classes['classes'] ) ? $block_style_classes['classes'] : '';
-			}
+			// Only apply the block style classes to the field wrapper if the field is one of the new inner block types.
+			$add_block_style_classes_to_field_wrapper = false;
 
 			foreach ( $block->parsed_block['innerBlocks'] as $inner_block ) {
 				$block_name = $inner_block['blockName'] ?? '';
 
 				if ( 'jetpack/label' === $block_name ) {
-					$atts['label']         = $inner_block['attrs']['label'] ?? $inner_block['attrs']['defaultLabel'] ?? '';
-					$atts['requiredText']  = $inner_block['attrs']['requiredText'] ?? null;
-					$label_attrs           = self::get_block_support_classes_and_styles( $block_name, $inner_block['attrs'] );
-					$atts['labelclasses']  = 'wp-block-jetpack-label';
-					$atts['labelclasses'] .= isset( $label_attrs['class'] ) ? ' ' . $label_attrs['class'] : '';
-					$atts['labelstyles']   = $label_attrs['style'] ?? null;
+					$atts['label']                            = $inner_block['attrs']['label'] ?? $inner_block['attrs']['defaultLabel'] ?? '';
+					$atts['requiredText']                     = $inner_block['attrs']['requiredText'] ?? null;
+					$label_attrs                              = self::get_block_support_classes_and_styles( $block_name, $inner_block['attrs'] );
+					$atts['labelclasses']                     = 'wp-block-jetpack-label';
+					$atts['labelclasses']                    .= isset( $label_attrs['class'] ) ? ' ' . $label_attrs['class'] : '';
+					$atts['labelstyles']                      = $label_attrs['style'] ?? null;
+					$add_block_style_classes_to_field_wrapper = true;
 				}
 
 				if ( 'jetpack/input' === $block_name ) {
@@ -473,14 +466,16 @@ public static function block_attributes_to_shortcode_attributes( $atts, $type, $
 					if ( 'jetpack/field-select' === $block->name ) {
 						$atts['togglelabel'] = $inner_block['attrs']['placeholder'];
 					}
+					$add_block_style_classes_to_field_wrapper = true;
 				}
 
 				// The following handles when option blocks are a direct inner block for a field e.g. singular checkbox field.
 				if ( 'jetpack/option' === $block_name ) {
-					$atts['label']         = $inner_block['attrs']['label'] ?? $inner_block['attrs']['defaultLabel'] ?? '';
-					$option_attrs          = self::get_block_support_classes_and_styles( $block_name, $inner_block['attrs'] );
-					$atts['optionclasses'] = isset( $option_attrs['class'] ) ? ' ' . $option_attrs['class'] : '';
-					$atts['optionstyles']  = $option_attrs['style'] ?? null;
+					$atts['label']                            = $inner_block['attrs']['label'] ?? $inner_block['attrs']['defaultLabel'] ?? '';
+					$option_attrs                             = self::get_block_support_classes_and_styles( $block_name, $inner_block['attrs'] );
+					$atts['optionclasses']                    = isset( $option_attrs['class'] ) ? ' ' . $option_attrs['class'] : '';
+					$atts['optionstyles']                     = $option_attrs['style'] ?? null;
+					$add_block_style_classes_to_field_wrapper = true;
 				}
 
 				// The following handles choice fields such as; Single Choice Field (radio) or Multiple Choice Field (checkbox).
@@ -508,8 +503,25 @@ public static function block_attributes_to_shortcode_attributes( $atts, $type, $
 						}
 					}
 
-					$atts['options']     = implode( ',', $options );
-					$atts['optionsdata'] = \wp_json_encode( $options_data );
+					$atts['options']                          = implode( ',', $options );
+					$atts['optionsdata']                      = \wp_json_encode( $options_data );
+					$add_block_style_classes_to_field_wrapper = true;
+				}
+			}
+
+			/*
+			 * Add the `wp-block-jetpack-field-*` and `is-style-*` classes to the field wrapper div
+			 * for fields that are one of the new inner block types.
+			 * This ensures any updates to field block styles in theme.json or global styles are
+			 * correctly applied.
+			 */
+			if ( $add_block_style_classes_to_field_wrapper ) {
+				$atts['fieldwrapperclasses'] = 'wp-block-jetpack-field-' . $type;
+				if ( ! empty( $atts['class'] ) ) {
+					$block_style_classes          = self::get_block_style_classes( $atts['class'] );
+					$atts['fieldwrapperclasses'] .= $block_style_classes['fieldwrapperclasses'];
+					// Return the rest of the classes without the block style classes.
+					$atts['class'] = $block_style_classes['classes'];
 				}
 			}
 		}
diff --git a/projects/packages/forms/tests/php/contact-form/Contact_Form_Plugin_Test.php b/projects/packages/forms/tests/php/contact-form/Contact_Form_Plugin_Test.php
index 5b4823153ea9..65aaa56de43c 100644
--- a/projects/packages/forms/tests/php/contact-form/Contact_Form_Plugin_Test.php
+++ b/projects/packages/forms/tests/php/contact-form/Contact_Form_Plugin_Test.php
@@ -125,7 +125,7 @@ public function test_gutenblock_render_field_checkbox_multiple_shortcode() {
 
 		// Render the shortcode.
 		$shortcode = Contact_Form_Plugin::gutenblock_render_field_checkbox_multiple( array(), '', new WP_Block( $block ) );
-		$expected  = '[contact-field type="checkbox-multiple" fieldwrapperclasses="wp-block-jetpack-field-checkbox-multiple" label="Choose several options" labelclasses="wp-block-jetpack-label has-text-color has-swamp-green-color" options="truth,dare" optionsdata="&#091;{&quot;label&quot;:&quot;truth&quot;&#044;&quot;class&quot;:&quot;has-text-color&quot;&#044;&quot;style&quot;:&quot;color:caramel; font-size:24px;&quot;}&#044;{&quot;label&quot;:&quot;dare&quot;&#044;&quot;class&quot;:&quot;has-text-color&quot;&#044;&quot;style&quot;:&quot;color:gummy; font-size:24px;&quot;}&#093;"/]';
+		$expected  = '[contact-field type="checkbox-multiple" label="Choose several options" labelclasses="wp-block-jetpack-label has-text-color has-swamp-green-color" options="truth,dare" optionsdata="&#091;{&quot;label&quot;:&quot;truth&quot;&#044;&quot;class&quot;:&quot;has-text-color&quot;&#044;&quot;style&quot;:&quot;color:caramel; font-size:24px;&quot;}&#044;{&quot;label&quot;:&quot;dare&quot;&#044;&quot;class&quot;:&quot;has-text-color&quot;&#044;&quot;style&quot;:&quot;color:gummy; font-size:24px;&quot;}&#093;" fieldwrapperclasses="wp-block-jetpack-field-checkbox-multiple"/]';
 
 		$this->assertEquals( $expected, $shortcode, 'Shortcode is not as expected' );
 	}
@@ -159,7 +159,7 @@ public function test_gutenblock_render_field_checkbox_shortcode() {
 			),
 		);
 		$shortcode = Contact_Form_Plugin::gutenblock_render_field_checkbox( array(), '', new WP_Block( $block ) );
-		$expected  = '[contact-field type="checkbox" fieldwrapperclasses="wp-block-jetpack-field-checkbox" label="single" optionclasses=" has-text-color" optionstyles="color:caramel; font-size:24px;"/]';
+		$expected  = '[contact-field type="checkbox" label="single" optionclasses=" has-text-color" optionstyles="color:caramel; font-size:24px;" fieldwrapperclasses="wp-block-jetpack-field-checkbox"/]';
 
 		$this->assertEquals( $expected, $shortcode );
 	}
@@ -209,7 +209,7 @@ public function test_gutenblock_gutenblock_render_field_text_shortcode() {
 			),
 		);
 		$shortcode = Contact_Form_Plugin::gutenblock_render_field_text( array(), '', new WP_Block( $block ) );
-		$expected  = '[contact-field type="text" fieldwrapperclasses="wp-block-jetpack-field-text" label="Label" requiredText="Do it" labelclasses="wp-block-jetpack-label has-text-color" labelstyles="color:caramel; font-size:24px;" placeholder="hi!" min="1" max="10" inputclasses="wp-block-jetpack-input has-text-color has-border-color" inputstyles="color:toot; font-size:33rem; border-color:toot;border-width:1px;"/]';
+		$expected  = '[contact-field type="text" label="Label" requiredText="Do it" labelclasses="wp-block-jetpack-label has-text-color" labelstyles="color:caramel; font-size:24px;" placeholder="hi!" min="1" max="10" inputclasses="wp-block-jetpack-input has-text-color has-border-color" inputstyles="color:toot; font-size:33rem; border-color:toot;border-width:1px;" fieldwrapperclasses="wp-block-jetpack-field-text"/]';
 
 		$this->assertEquals( $expected, $shortcode );
 	}
@@ -282,7 +282,7 @@ public function test_gutenblock_gutenblock_render_field_radio() {
 
 		// Render the shortcode.
 		$shortcode = Contact_Form_Plugin::gutenblock_render_field_radio( array(), '', new WP_Block( $block ) );
-		$expected  = '[contact-field type="radio" fieldwrapperclasses="wp-block-jetpack-field-radio" label="Radio gaga" labelclasses="wp-block-jetpack-label has-text-color has-turmoil-purple-color" options="freddy,brian" optionsdata="&#091;{&quot;label&quot;:&quot;freddy&quot;&#044;&quot;class&quot;:&quot;has-text-color&quot;&#044;&quot;style&quot;:&quot;color:reddo; font-size:24px;&quot;}&#044;{&quot;label&quot;:&quot;brian&quot;&#044;&quot;class&quot;:&quot;has-text-color&quot;&#044;&quot;style&quot;:&quot;color:blueo; font-size:100rem;&quot;}&#093;"/]';
+		$expected  = '[contact-field type="radio" label="Radio gaga" labelclasses="wp-block-jetpack-label has-text-color has-turmoil-purple-color" options="freddy,brian" optionsdata="&#091;{&quot;label&quot;:&quot;freddy&quot;&#044;&quot;class&quot;:&quot;has-text-color&quot;&#044;&quot;style&quot;:&quot;color:reddo; font-size:24px;&quot;}&#044;{&quot;label&quot;:&quot;brian&quot;&#044;&quot;class&quot;:&quot;has-text-color&quot;&#044;&quot;style&quot;:&quot;color:blueo; font-size:100rem;&quot;}&#093;" fieldwrapperclasses="wp-block-jetpack-field-radio"/]';
 
 		$this->assertEquals( $expected, $shortcode, 'Shortcode is not as expected' );
 	}


Reviews:
user: login: talldan
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-28T10:01:18Z
user: login: ramonjd
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-28T10:07:08Z
user: login: talldan
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-28T10:17:32Z
user: login: talldan
body: Thanks for the fix. It's working well for me, the only very minor thing I noticed is that with this PR checked out, the non-upgraded block seems to have a space at the start of its class name:
<img width="439" alt="Screenshot 2025-04-28 at 5 43 04 pm" src="https://github.com/user-attachments/assets/f21c60f6-4810-4ba3-bc6c-2e1cce8b12e5" />

It's probably not this PR, but the upstream branch that introduces this, as I can't see any code that might cause it in the diff.

I also left a small code comment, but it doesn't look like a bug, just a code quality thing.
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-28T10:26:34Z
user: login: ramonjd
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-28T10:27:26Z
user: login: andrewserong
body: I see Dan's already given this a review, but just a quick drive by that this is looking good to me, too! 🚀 
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-29T00:53:25Z
user: login: ramonjd
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-29T01:21:04Z

Review comments:
diff_hunk: @@ -508,8 +500,26 @@ public static function block_attributes_to_shortcode_attributes( $atts, $type, $
 						}
 					}
 
-					$atts['options']     = implode( ',', $options );
-					$atts['optionsdata'] = \wp_json_encode( $options_data );
+					$atts['options']                          = implode( ',', $options );
+					$atts['optionsdata']                      = \wp_json_encode( $options_data );
+					$add_block_style_classes_to_field_wrapper = true;
+				}
+			}
+
+			/*
+			 * Add the `wp-block-jetpack-field-*` and `is-style-*` classes to the field wrapper div
+			 * for fields that are one of the new inner block types.
+			 * This ensures any updates to field block styles in theme.json or global styles are
+			 * correctly applied.
+			 */
+			if ( $add_block_style_classes_to_field_wrapper ) {
+				$atts['fieldwrapperclasses'] = 'wp-block-jetpack-field-' . $type;
+				if ( ! empty( $atts['class'] ) ) {
+					$block_style_classes          = self::get_block_style_classes( $atts['class'] );
+					$spacer                       = ! empty( $block_style_classes['block_style_classes'] ) ? ' ' : '';
+					$atts['fieldwrapperclasses'] .= $spacer . $block_style_classes['block_style_classes'] . $spacer . $block_style_classes['wrap_classes'];
path: projects/packages/forms/src/contact-form/class-contact-form-plugin.php
user: login: talldan
body: Is there a case that ` $block_style_classes['block_style_classes']` could be empty, while `$block_style_classes['wrap_classes']` contains a value?

As in that situation it looks like it'll be appended straight onto `$atts['fieldwrapperclasses']` without any spaces between them.
created_at: 2025-04-28T10:01:18Z
author_association: CONTRIBUTOR
diff_hunk: @@ -508,8 +500,26 @@ public static function block_attributes_to_shortcode_attributes( $atts, $type, $
 						}
 					}
 
-					$atts['options']     = implode( ',', $options );
-					$atts['optionsdata'] = \wp_json_encode( $options_data );
+					$atts['options']                          = implode( ',', $options );
+					$atts['optionsdata']                      = \wp_json_encode( $options_data );
+					$add_block_style_classes_to_field_wrapper = true;
+				}
+			}
+
+			/*
+			 * Add the `wp-block-jetpack-field-*` and `is-style-*` classes to the field wrapper div
+			 * for fields that are one of the new inner block types.
+			 * This ensures any updates to field block styles in theme.json or global styles are
+			 * correctly applied.
+			 */
+			if ( $add_block_style_classes_to_field_wrapper ) {
+				$atts['fieldwrapperclasses'] = 'wp-block-jetpack-field-' . $type;
+				if ( ! empty( $atts['class'] ) ) {
+					$block_style_classes          = self::get_block_style_classes( $atts['class'] );
+					$spacer                       = ! empty( $block_style_classes['block_style_classes'] ) ? ' ' : '';
+					$atts['fieldwrapperclasses'] .= $spacer . $block_style_classes['block_style_classes'] . $spacer . $block_style_classes['wrap_classes'];
path: projects/packages/forms/src/contact-form/class-contact-form-plugin.php
user: login: ramonjd
body: Good question. No, since if there are no block style classes there will be no wrap classes.

See: https://github.com/Automattic/jetpack/blob/update/only-apply-block-classes-to-new-inner-blocks-field-wrappers/projects/packages/forms/src/contact-form/class-contact-form-plugin.php#L403

I should probably make it more explicit or clear. 
created_at: 2025-04-28T10:07:08Z
author_association: MEMBER
diff_hunk: @@ -508,8 +500,26 @@ public static function block_attributes_to_shortcode_attributes( $atts, $type, $
 						}
 					}
 
-					$atts['options']     = implode( ',', $options );
-					$atts['optionsdata'] = \wp_json_encode( $options_data );
+					$atts['options']                          = implode( ',', $options );
+					$atts['optionsdata']                      = \wp_json_encode( $options_data );
+					$add_block_style_classes_to_field_wrapper = true;
+				}
+			}
+
+			/*
+			 * Add the `wp-block-jetpack-field-*` and `is-style-*` classes to the field wrapper div
+			 * for fields that are one of the new inner block types.
+			 * This ensures any updates to field block styles in theme.json or global styles are
+			 * correctly applied.
+			 */
+			if ( $add_block_style_classes_to_field_wrapper ) {
+				$atts['fieldwrapperclasses'] = 'wp-block-jetpack-field-' . $type;
+				if ( ! empty( $atts['class'] ) ) {
+					$block_style_classes          = self::get_block_style_classes( $atts['class'] );
+					$spacer                       = ! empty( $block_style_classes['block_style_classes'] ) ? ' ' : '';
+					$atts['fieldwrapperclasses'] .= $spacer . $block_style_classes['block_style_classes'] . $spacer . $block_style_classes['wrap_classes'];
path: projects/packages/forms/src/contact-form/class-contact-form-plugin.php
user: login: talldan
body: Ok, I debugged it a bit. It looks like both contain the same thing, the block variation style classname, but one has  `-wrap` appended to the end.

It makes me wonder why `get_block_style_classes` returns them as separate properties if they end up appended together.

edit: oops, I didn't see your comment until after I posted this.
created_at: 2025-04-28T10:17:31Z
author_association: CONTRIBUTOR
diff_hunk: @@ -508,8 +500,26 @@ public static function block_attributes_to_shortcode_attributes( $atts, $type, $
 						}
 					}
 
-					$atts['options']     = implode( ',', $options );
-					$atts['optionsdata'] = \wp_json_encode( $options_data );
+					$atts['options']                          = implode( ',', $options );
+					$atts['optionsdata']                      = \wp_json_encode( $options_data );
+					$add_block_style_classes_to_field_wrapper = true;
+				}
+			}
+
+			/*
+			 * Add the `wp-block-jetpack-field-*` and `is-style-*` classes to the field wrapper div
+			 * for fields that are one of the new inner block types.
+			 * This ensures any updates to field block styles in theme.json or global styles are
+			 * correctly applied.
+			 */
+			if ( $add_block_style_classes_to_field_wrapper ) {
+				$atts['fieldwrapperclasses'] = 'wp-block-jetpack-field-' . $type;
+				if ( ! empty( $atts['class'] ) ) {
+					$block_style_classes          = self::get_block_style_classes( $atts['class'] );
+					$spacer                       = ! empty( $block_style_classes['block_style_classes'] ) ? ' ' : '';
+					$atts['fieldwrapperclasses'] .= $spacer . $block_style_classes['block_style_classes'] . $spacer . $block_style_classes['wrap_classes'];
path: projects/packages/forms/src/contact-form/class-contact-form-plugin.php
user: login: ramonjd
body: > It makes me wonder why get_block_style_classes returns them as separate properties if they end up appended together.

Oh, yeah I think I was doing something else at some stage and forgot to join them 😄 

If you want to join in on the confusion, take a look at [render_field](https://github.com/Automattic/jetpack/blob/update/only-apply-block-classes-to-new-inner-blocks-field-wrappers/projects/packages/forms/src/contact-form/class-contact-form-field.php#L1494) - it does some funky stuff. 

I'll update tomorrow.


created_at: 2025-04-28T10:27:26Z
author_association: MEMBER
diff_hunk: @@ -508,8 +500,26 @@ public static function block_attributes_to_shortcode_attributes( $atts, $type, $
 						}
 					}
 
-					$atts['options']     = implode( ',', $options );
-					$atts['optionsdata'] = \wp_json_encode( $options_data );
+					$atts['options']                          = implode( ',', $options );
+					$atts['optionsdata']                      = \wp_json_encode( $options_data );
+					$add_block_style_classes_to_field_wrapper = true;
+				}
+			}
+
+			/*
+			 * Add the `wp-block-jetpack-field-*` and `is-style-*` classes to the field wrapper div
+			 * for fields that are one of the new inner block types.
+			 * This ensures any updates to field block styles in theme.json or global styles are
+			 * correctly applied.
+			 */
+			if ( $add_block_style_classes_to_field_wrapper ) {
+				$atts['fieldwrapperclasses'] = 'wp-block-jetpack-field-' . $type;
+				if ( ! empty( $atts['class'] ) ) {
+					$block_style_classes          = self::get_block_style_classes( $atts['class'] );
+					$spacer                       = ! empty( $block_style_classes['block_style_classes'] ) ? ' ' : '';
+					$atts['fieldwrapperclasses'] .= $spacer . $block_style_classes['block_style_classes'] . $spacer . $block_style_classes['wrap_classes'];
path: projects/packages/forms/src/contact-form/class-contact-form-plugin.php
user: login: ramonjd
body: I merged the field classes and wrap in [b990885](https://github.com/Automattic/jetpack/pull/43268/commits/b990885f9ca20d2ce0d6f7a873576b466b64b5d2)
created_at: 2025-04-29T01:21:04Z
author_association: MEMBER

PR comments:
user: login: github-actions[bot]
created_at: 2025-04-28T02:48:40Z
body: <!-- wpcom-reminder-comment -->
Are you an Automattician? Please test your changes on all WordPress.com environments to help mitigate accidental explosions.

- To test on WoA, go to the Plugins menu on a WoA dev site. Click on the "Upload" button and follow the upgrade flow to be able to upload, install, and activate [the Jetpack Beta plugin](https://jetpack.com/download-jetpack-beta/). Once the plugin is active, go to Jetpack > Jetpack Beta, select your plugin (Jetpack), and enable the `update/only-apply-block-classes-to-new-inner-blocks-field-wrappers` branch.
- To test on Simple, run the following command on your sandbox:
```
bin/jetpack-downloader test jetpack update/only-apply-block-classes-to-new-inner-blocks-field-wrappers
```

*Interested in more tips and information?*

- In your local development environment, use the `jetpack rsync` command to sync your changes to a WoA dev blog.
- Read more about our development workflow here: PCYsg-eg0-p2
- Figure out **when your changes will be shipped to customers** here: PCYsg-eg5-p2
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-04-28T02:48:59Z
body: **Thank you for your PR!**

When contributing to Jetpack, we have [a few suggestions](https://github.com/Automattic/jetpack/blob/trunk/.github/PULL_REQUEST_TEMPLATE.md) that can help us test and review your patch:<br>
- :white_check_mark: Include a description of your PR changes.<br>
- :white_check_mark: Add a "[Status]" label (In Progress, Needs Review, ...).<br>
- :red_circle: Add a "[Type]" label (Bug, Enhancement, Janitorial, Task).<br>
- :white_check_mark: Add testing instructions.<br>
- :red_circle: Specify whether this PR includes any changes to data or privacy.<br>
- :red_circle: Add changelog entries to affected projects<br>


This comment will be updated as you work on your PR and make changes. If you think that some of those checks are not needed for your PR, please explain why you think so. Thanks for cooperation :robot:

******
:red_circle: **Action required:** We would recommend that you add a section to the PR description to specify whether this PR includes any changes to data or privacy, like so:
~~~
## Does this pull request change what data or activity we track or use?

My PR adds *x* and *y*.
~~~

******
:red_circle: **Action required:** Please add missing changelog entries for the following projects: `projects/packages/forms`

Use [the Jetpack CLI tool](https://github.com/Automattic/jetpack/blob/trunk/docs/monorepo.md#first-time) to generate changelog entries by running the following command: `jetpack changelog add`.
Guidelines: [/docs/writing-a-good-changelog-entry.md](https://github.com/Automattic/jetpack/blob/trunk/docs/writing-a-good-changelog-entry.md)


******

**Follow this PR Review Process:**

1. Ensure all required checks appearing at the bottom of this PR are passing.
2. Make sure to test your changes on all platforms that it applies to. *You're responsible for the quality of the code you ship*.
3. You can use [GitHub's Reviewers functionality](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/requesting-a-pull-request-review) to request a review.
4. When it's reviewed and merged, you will be pinged in Slack to deploy the changes to WordPress.com simple once the build is done.

If you have questions about anything, reach out in #jetpack-developers for guidance!
author_association: CONTRIBUTOR
user: login: jp-launch-control[bot]
created_at: 2025-04-28T02:57:09Z
body: ### Code Coverage Summary

No summary data is available for parent commit d9b72693, so cannot calculate coverage changes. :sleeping:

If that commit is a feature branch rather than a trunk commit, this is expected. Otherwise, this should be updated once coverage for d9b72693 is available.

[Full summary](https://jetpackcodecoverage.atomicsites.blog/prs/43268/) · [PHP report](https://jetpackcodecoverage.atomicsites.blog/prs/43268/php/) · [JS report](https://jetpackcodecoverage.atomicsites.blog/prs/43268/js/)
author_association: NONE
user: login: ramonjd
created_at: 2025-04-28T10:28:49Z
body: > the non-upgraded block seems to have a space at the start of its class name

Thanks @talldan 

It could be this PR, or the one that preceded it: https://github.com/Automattic/jetpack/pull/43184

I'll follow up on this. Thanks!
author_association: MEMBER
user: login: ramonjd
created_at: 2025-04-29T01:21:31Z
body: > the non-upgraded block seems to have a space at the start of its class name

Found it and removed it. 

Thanks for the ✅ , folks!
author_association: MEMBER