Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
637de48
Forms: add conditional logic to form fields
enejb Aug 10, 2026
97dde97
Forms: store conditional logic as groups of rules
enejb Aug 12, 2026
49b1756
Forms: fix conditional-logic CI failures on the resolver
kraftbj Aug 12, 2026
6db0e02
Forms: align the conditional-logic descriptor array keys
kraftbj Aug 12, 2026
c87bfbc
Forms: give rating fields their own comparison behaviour
enejb Aug 13, 2026
db066d6
Forms: edit conditional logic in a dialog instead of the inspector
enejb Aug 13, 2026
70c0185
Forms: restore the two-selector heading and give conditions a surface
enejb Aug 13, 2026
4d00246
Forms: centre the condition rows and let the heading selectors size t…
enejb Aug 13, 2026
9235ebd
Forms: show whether a condition is finished, and start the author off…
enejb Aug 13, 2026
d0fc1c3
Forms: centre the inspector button, align the hint, and follow focus …
enejb Aug 13, 2026
f3ebf89
Forms: report conditional logic in the block toolbar
enejb Aug 13, 2026
12f04e0
Forms: invert the conditional-logic toolbar button while conditions e…
enejb Aug 13, 2026
b220d19
Forms: keep the conditional-logic toolbar button on every field that …
enejb Aug 13, 2026
da4d160
Forms: add Clear all conditions, and offer Add only when it can act
enejb Aug 13, 2026
c2c6a5c
Forms: badge each condition active or inactive, and always offer Add
enejb Aug 14, 2026
c47024d
Forms: put the condition badge after the remove control and size it t…
enejb Aug 14, 2026
b364c60
Forms: say what the field does before any condition is met
enejb Aug 14, 2026
7a93684
Forms: show the field's starting state in the toolbar icon
enejb Aug 14, 2026
ebbd3f5
Forms: mark condition state with an icon at the head of the row
enejb Aug 14, 2026
106d6f0
Forms: test the subject-field hooks directly
enejb Aug 14, 2026
5898fc1
Forms: use the token variants that actually carry the status hue
enejb Aug 14, 2026
bf8fd6d
Forms: actually skip a condition that was never given a value
enejb Aug 14, 2026
d83f3a0
Forms: keep conditional labels extractable in the production build
enejb Aug 14, 2026
c31bbd6
Forms: align conditional field visibility
kraftbj Aug 14, 2026
c85467a
Forms: list a field's conditions in the inspector instead of counting…
enejb Aug 14, 2026
29e4183
Forms: name the field type in the summary, and highlight the field on…
enejb Aug 14, 2026
52d7c3a
Forms: remove Clear all conditions
enejb Aug 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions projects/packages/forms/changelog/try-conditional-form-fields
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: minor
Type: added

Add conditional logic to form fields, so any field can be shown or hidden based on another field's answer. Disabled by default while in testing; enable it with the forms-conditional-logic feature flag.
1 change: 1 addition & 0 deletions projects/packages/forms/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"automattic/jetpack-connection": "@dev",
"automattic/jetpack-device-detection": "@dev",
"automattic/jetpack-external-connections": "@dev",
"automattic/jetpack-feature-flags": "@dev",
"automattic/jetpack-jwt": "@dev",
"automattic/jetpack-logo": "@dev",
"automattic/jetpack-menu-badges": "@dev",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { hasFeatureFlag } from '@automattic/jetpack-shared-extension-utils';
// Side-effect import: registers the editor.BlockEdit filter that adds the conditional-logic
// panel to every jetpack/field-* block.
import '../shared/conditional-logic/register.jsx';
import DeprecatedOptionCheckbox from '../deprecated/field-option-checkbox/index.js';
import DeprecatedOptionRadio from '../deprecated/field-option-radio/index.js';
import JetpackDropzone from '../dropzone/index.jsx';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,10 @@ public static function register_feature( $features ) {
$features['multistep-form'] = Current_Plan::supports( 'multistep-form' );
$features['form-webhooks'] = Current_Plan::supports( 'form-webhooks' );

// Bridges the jetpack-feature-flags registration to the editor, so JS `hasFeatureFlag()`
// and PHP `Feature_Flags::is_enabled()` answer from one source under one name.
$features[ Jetpack_Forms::CONDITIONAL_LOGIC_FLAG ] = Jetpack_Forms::is_conditional_logic_enabled();

return self::register_central_form_management_default( $features );
}

Expand Down
11 changes: 11 additions & 0 deletions projects/packages/forms/src/blocks/field-checkbox/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@ export const form_editor = {
category: 'choice',
};

/**
* Conditional logic: how this field's value is compared.
*
* Declared per block so the rule builder can offer the right operators and value
* input. A block that omits this simply gets no conditional-logic support.
*/
export const conditional_logic = {
type: 'boolean',
};

export const settings = {
...defaultSettings,
title: __( 'Checkbox', 'jetpack-forms' ),
Expand Down Expand Up @@ -49,4 +59,5 @@ export default {
name,
settings,
form_editor,
conditional_logic,
};
11 changes: 11 additions & 0 deletions projects/packages/forms/src/blocks/field-consent/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@ export const form_editor = {
category: 'advanced',
};

/**
* Conditional logic: how this field's value is compared.
*
* Declared per block so the rule builder can offer the right operators and value
* input. A block that omits this simply gets no conditional-logic support.
*/
export const conditional_logic = {
type: 'boolean',
};

export const settings = {
...defaultSettings,
title: __( 'Terms consent', 'jetpack-forms' ),
Expand Down Expand Up @@ -70,4 +80,5 @@ export default {
name,
settings,
form_editor,
conditional_logic,
};
11 changes: 11 additions & 0 deletions projects/packages/forms/src/blocks/field-date/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@ export const form_editor = {
category: 'advanced',
};

/**
* Conditional logic: how this field's value is compared.
*
* Declared per block so the rule builder can offer the right operators and value
* input. A block that omits this simply gets no conditional-logic support.
*/
export const conditional_logic = {
type: 'date',
};

export const settings = {
...defaultSettings,
title: __( 'Date picker', 'jetpack-forms' ),
Expand Down Expand Up @@ -56,4 +66,5 @@ export default {
name,
settings,
form_editor,
conditional_logic,
};
11 changes: 11 additions & 0 deletions projects/packages/forms/src/blocks/field-email/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,16 @@ export const form_editor = {
category: 'contact-info',
};

/**
* Conditional logic: how this field's value is compared.
*
* Declared per block so the rule builder can offer the right operators and value
* input. A block that omits this simply gets no conditional-logic support.
*/
export const conditional_logic = {
type: 'string',
};

export const settings = {
...defaultSettings,
title: __( 'Email field', 'jetpack-forms' ),
Expand Down Expand Up @@ -45,4 +55,5 @@ export default {
name,
settings,
form_editor,
conditional_logic,
};
11 changes: 11 additions & 0 deletions projects/packages/forms/src/blocks/field-file/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@ export const form_editor = {
category: 'advanced',
};

/**
* Conditional logic: how this field's value is compared.
*
* Declared per block so the rule builder can offer the right operators and value
* input. A block that omits this simply gets no conditional-logic support.
*/
export const conditional_logic = {
type: 'file',
};

export const settings = {
...defaultSettings,
title: __( 'File upload field', 'jetpack-forms' ),
Expand Down Expand Up @@ -45,4 +55,5 @@ export default {
name,
settings,
form_editor,
conditional_logic,
};
11 changes: 11 additions & 0 deletions projects/packages/forms/src/blocks/field-hidden/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,16 @@ export const form_editor = {
category: 'advanced',
};

/**
* Conditional logic: how this field's value is compared.
*
* Declared per block so the rule builder can offer the right operators and value
* input. A block that omits this simply gets no conditional-logic support.
*/
export const conditional_logic = {
type: 'hidden',
};

export const settings = {
...defaultSettings,
title: __( 'Hidden field', 'jetpack-forms' ),
Expand Down Expand Up @@ -39,4 +49,5 @@ export default {
name,
settings,
form_editor,
conditional_logic,
};
14 changes: 14 additions & 0 deletions projects/packages/forms/src/blocks/field-image-select/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,20 @@ export const form_editor = {
category: 'choice',
};

/*
* Deliberately no `conditional_logic` declaration, so this block gets no panel.
*
* An image-select field submits a JSON document describing the choice
* (`{"perceived":"A","selected":"a","label":"Blue",...}`), not the label the rule builder
* offers as a value. All three evaluators would compare that document against `Blue` and
* never match, so `is` would be permanently false and `is not` permanently true: a rule
* would hide its field forever and the answer would then be dropped at storage.
*
* Comparing the decoded `label` in every evaluator is the real fix, but that is value-shape
* handling in exactly the place where the JS and PHP evaluators already drift. Offering no
* rule is better than offering one that cannot fire.
*/

export const settings = {
...defaultSettings,
title: __( 'Image Select Field', 'jetpack-forms' ),
Expand Down
11 changes: 11 additions & 0 deletions projects/packages/forms/src/blocks/field-multiple-choice/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@ export const form_editor = {
category: 'choice',
};

/**
* Conditional logic: how this field's value is compared.
*
* Declared per block so the rule builder can offer the right operators and value
* input. A block that omits this simply gets no conditional-logic support.
*/
export const conditional_logic = {
type: 'multichoice',
};

export const settings = {
...defaultSettings,
title: __( 'Multiple choice (checkbox)', 'jetpack-forms' ),
Expand Down Expand Up @@ -70,4 +80,5 @@ export default {
name,
settings,
form_editor,
conditional_logic,
};
11 changes: 11 additions & 0 deletions projects/packages/forms/src/blocks/field-name/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,16 @@ export const form_editor = {
category: 'contact-info',
};

/**
* Conditional logic: how this field's value is compared.
*
* Declared per block so the rule builder can offer the right operators and value
* input. A block that omits this simply gets no conditional-logic support.
*/
export const conditional_logic = {
type: 'string',
};

const transforms = {
...transformsSource,
to: transformsSource.to.filter( transform => ! transform.blocks.includes( 'jetpack/' + name ) ),
Expand Down Expand Up @@ -57,4 +67,5 @@ export default {
name,
settings,
form_editor,
conditional_logic,
};
11 changes: 11 additions & 0 deletions projects/packages/forms/src/blocks/field-number/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@ export const form_editor = {
category: 'basic',
};

/**
* Conditional logic: how this field's value is compared.
*
* Declared per block so the rule builder can offer the right operators and value
* input. A block that omits this simply gets no conditional-logic support.
*/
export const conditional_logic = {
type: 'number',
};

export const settings = {
...defaultSettings,
title: __( 'Number input field', 'jetpack-forms' ),
Expand Down Expand Up @@ -41,4 +51,5 @@ export default {
name,
settings,
form_editor,
conditional_logic,
};
12 changes: 11 additions & 1 deletion projects/packages/forms/src/blocks/field-rating/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@ export const form_editor = {
category: 'advanced',
};

/**
* Conditional logic: how this field's value is compared.
*
* Declared per block so the rule builder can offer the right operators and value
* input. A block that omits this simply gets no conditional-logic support.
*/
export const conditional_logic = {
type: 'rating',
};

export const settings = {
...defaultSettings,
title: __( 'Rating field', 'jetpack-forms' ),
Expand Down Expand Up @@ -60,4 +70,4 @@ export const settings = {
},
};

export default { name, settings, form_editor };
export default { name, settings, form_editor, conditional_logic };
11 changes: 11 additions & 0 deletions projects/packages/forms/src/blocks/field-select/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@ export const form_editor = {
category: 'choice',
};

/**
* Conditional logic: how this field's value is compared.
*
* Declared per block so the rule builder can offer the right operators and value
* input. A block that omits this simply gets no conditional-logic support.
*/
export const conditional_logic = {
type: 'choice',
};

export const settings = {
...defaultSettings,
title: __( 'Dropdown field', 'jetpack-forms' ),
Expand Down Expand Up @@ -62,4 +72,5 @@ export default {
name,
settings,
form_editor,
conditional_logic,
};
11 changes: 11 additions & 0 deletions projects/packages/forms/src/blocks/field-single-choice/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@ export const form_editor = {
category: 'choice',
};

/**
* Conditional logic: how this field's value is compared.
*
* Declared per block so the rule builder can offer the right operators and value
* input. A block that omits this simply gets no conditional-logic support.
*/
export const conditional_logic = {
type: 'choice',
};

export const settings = {
...defaultSettings,
title: __( 'Single choice (radio)', 'jetpack-forms' ),
Expand Down Expand Up @@ -68,4 +78,5 @@ export default {
name,
settings,
form_editor,
conditional_logic,
};
11 changes: 11 additions & 0 deletions projects/packages/forms/src/blocks/field-slider/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,16 @@ export const form_editor = {
category: 'advanced',
};

/**
* Conditional logic: how this field's value is compared.
*
* Declared per block so the rule builder can offer the right operators and value
* input. A block that omits this simply gets no conditional-logic support.
*/
export const conditional_logic = {
type: 'number',
};

export const settings = {
...defaultSettings,
title: __( 'Slider field', 'jetpack-forms' ),
Expand Down Expand Up @@ -85,4 +95,5 @@ export default {
name,
settings,
form_editor,
conditional_logic,
};
11 changes: 11 additions & 0 deletions projects/packages/forms/src/blocks/field-telephone/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,16 @@ export const form_editor = {
category: 'contact-info',
};

/**
* Conditional logic: how this field's value is compared.
*
* Declared per block so the rule builder can offer the right operators and value
* input. A block that omits this simply gets no conditional-logic support.
*/
export const conditional_logic = {
type: 'string',
};

export const settings = {
...defaultSettings,
title: __( 'Phone number field', 'jetpack-forms' ),
Expand Down Expand Up @@ -74,4 +84,5 @@ export default {
name,
settings,
form_editor,
conditional_logic,
};
9 changes: 9 additions & 0 deletions projects/packages/forms/src/blocks/field-text/edit.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@ import { __ } from '@wordpress/i18n';
import JetpackField from '../shared/components/jetpack-field.jsx';
import useFormWrapper from '../shared/hooks/use-form-wrapper.js';

/**
* Editor component for the jetpack/field-text block.
*
* The conditional-logic panel is not wired up here: an `editor.BlockEdit` filter adds it to
* every `jetpack/field-*` block, this one included.
*
* @param {object} props - Block editor props passed in by Gutenberg.
* @return {object} The text field editor markup.
*/
export default function TextFieldEdit( props ) {
useFormWrapper( props );

Expand Down
Loading
Loading