Skip to content

Commit 422014f

Browse files
authored
Forms: Add dots style variant to form progress indicator block (#44582)
1 parent 7caa95f commit 422014f

File tree

13 files changed

+656
-119
lines changed

13 files changed

+656
-119
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Significance: minor
2+
Type: added
3+
4+
Forms: Progress Indicator: Dots Style

projects/packages/forms/src/blocks/contact-form/class-contact-form-block.php

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ public static function register_block() {
4848
add_filter( 'render_block_data', array( __CLASS__, 'find_nested_html_block' ), 10, 3 );
4949
add_filter( 'render_block_core/html', array( __CLASS__, 'render_wrapped_html_block' ), 10, 2 );
5050
add_filter( 'jetpack_block_editor_feature_flags', array( __CLASS__, 'register_feature' ) );
51+
add_filter( 'pre_render_block', array( __CLASS__, 'pre_render_contact_form' ), 10, 3 );
5152
}
5253
/**
5354
* Register the contact form block feature flag.
@@ -486,6 +487,71 @@ public static function set_file_field_extension_available() {
486487
}
487488
}
488489

490+
/**
491+
* Render the gutenblock form.
492+
*
493+
* @param array $atts - the block attributes.
494+
* @param string $content - html content.
495+
*
496+
* @return string
497+
*/
498+
/**
499+
* Static storage for form step count.
500+
*
501+
* @var int
502+
*/
503+
private static $form_step_count = 1;
504+
505+
/**
506+
* Hook into pre_render_block to count form steps before inner blocks render.
507+
*
508+
* @param string|null $pre_render The pre-rendered content. Default null.
509+
* @param array $parsed_block The block being rendered.
510+
* @return string|null
511+
*/
512+
public static function pre_render_contact_form( $pre_render, $parsed_block ) {
513+
// Only process contact form blocks
514+
if ( $parsed_block['blockName'] !== 'jetpack/contact-form' ) {
515+
return $pre_render;
516+
}
517+
518+
// Count and store form steps
519+
self::$form_step_count = self::count_form_steps_in_block( $parsed_block );
520+
521+
return $pre_render; // Don't actually pre-render, let normal rendering continue
522+
}
523+
524+
/**
525+
* Count form step blocks in a contact form block.
526+
*
527+
* @param array $block The contact form block.
528+
* @return int Number of form steps found.
529+
*/
530+
private static function count_form_steps_in_block( $block ) {
531+
$step_count = 0;
532+
533+
if ( isset( $block['innerBlocks'] ) ) {
534+
foreach ( $block['innerBlocks'] as $inner_block ) {
535+
if ( $inner_block['blockName'] === 'jetpack/form-step' ) {
536+
++$step_count;
537+
}
538+
// Also check nested blocks (like step containers)
539+
$step_count += self::count_form_steps_in_block( $inner_block );
540+
}
541+
}
542+
543+
return $step_count;
544+
}
545+
546+
/**
547+
* Get the step count for forms (used by progress indicator).
548+
*
549+
* @return int The step count.
550+
*/
551+
public static function get_form_step_count() {
552+
return self::$form_step_count;
553+
}
554+
489555
/**
490556
* Render the gutenblock form.
491557
*

projects/packages/forms/src/blocks/contact-form/edit.js

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
useInnerBlocksProps,
1111
store as blockEditorStore,
1212
BlockControls,
13+
BlockContextProvider,
1314
} from '@wordpress/block-editor';
1415
import { createBlock } from '@wordpress/blocks';
1516
import {
@@ -118,6 +119,12 @@ function JetpackContactFormEdit( { name, attributes, setAttributes, clientId, cl
118119

119120
const steps = useFormSteps( clientId );
120121

122+
// Get current step info for context
123+
const currentStepInfo = useSelect(
124+
select => select( singleStepStore ).getCurrentStepInfo( clientId, steps ),
125+
[ clientId, steps ]
126+
);
127+
121128
const submitButton = useFindBlockRecursively(
122129
clientId,
123130
block => block.name === 'jetpack/button'
@@ -785,7 +792,14 @@ function JetpackContactFormEdit( { name, attributes, setAttributes, clientId, cl
785792
{ __( 'Read more.', 'jetpack-forms' ) }
786793
</ExternalLink>
787794
</InspectorAdvancedControls>
788-
<div { ...innerBlocksProps } />
795+
<BlockContextProvider
796+
value={ {
797+
'jetpack/form-steps': steps,
798+
'jetpack/form-current-step': currentStepInfo,
799+
} }
800+
>
801+
<div { ...innerBlocksProps } />
802+
</BlockContextProvider>
789803
</>
790804
);
791805
}

projects/packages/forms/src/blocks/form-progress-indicator/edit.js

Lines changed: 105 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,120 @@
1-
import { useBlockProps } from '@wordpress/block-editor';
1+
/* eslint-disable @wordpress/no-unsafe-wp-apis */
2+
import {
3+
useBlockProps,
4+
InspectorControls,
5+
__experimentalColorGradientSettingsDropdown as ColorGradientSettingsDropdown,
6+
__experimentalUseMultipleOriginColorsAndGradients as useMultipleOriginColorsAndGradients,
7+
} from '@wordpress/block-editor';
8+
/* eslint-enable @wordpress/no-unsafe-wp-apis */
9+
import { SVG, Path } from '@wordpress/components';
10+
import { __ } from '@wordpress/i18n';
11+
import clsx from 'clsx';
212
import StepControls from '../shared/components/form-step-controls';
313
import useParentFormClientId from '../shared/hooks/use-parent-form-client-id';
4-
import useStepNavigation from '../shared/hooks/use-step-navigation';
14+
import { calculateProgressPercentage } from '../shared/util/progress-calculation';
515

6-
import './editor.scss';
16+
import './style.scss';
717

8-
const FormProgressIndicatorEdit = ( { clientId } ) => {
18+
const FormProgressIndicatorEdit = ( { clientId, context, attributes, setAttributes } ) => {
919
const parentFormId = useParentFormClientId( clientId );
10-
const { currentStepInfo, steps } = useStepNavigation( parentFormId );
1120

12-
let progress = steps.length ? ( ( currentStepInfo.index + 1 ) / steps.length ) * 100 : 10;
13-
if ( currentStepInfo.index === -1 && steps.length > 0 ) {
14-
progress = ( 1 / steps.length ) * 100; // Assume the first step is active
15-
}
21+
// Get data from context - provide mock data for previews when context is missing
22+
const steps = context?.[ 'jetpack/form-steps' ] || [ 1, 2, 3 ];
23+
const currentStepInfo = context?.[ 'jetpack/form-current-step' ] || { index: 0 };
24+
25+
// Extract attributes
26+
const { variant = 'line', progressColor, progressBackgroundColor, textColor, style } = attributes;
1627

17-
const blockProps = useBlockProps();
28+
// Get WordPress color/gradient settings for the color panel
29+
const colorGradientSettings = useMultipleOriginColorsAndGradients();
1830

19-
// Only need to set width – colours come from core style engine variables.
20-
const progressBarStyle = {
21-
width: `${ progress }%`,
31+
// Build style object with CSS custom properties for colors
32+
const colorStyles = {
33+
'--jp-progress-active-color': progressColor,
34+
'--jp-progress-track-color': progressBackgroundColor,
35+
// Text color comes from standard color support
36+
'--jp-progress-text-color': textColor || style?.color?.text,
2237
};
2338

39+
const blockProps = useBlockProps( {
40+
style: colorStyles,
41+
className: `is-variant-${ variant }`,
42+
} );
43+
const isDotStyle = variant === 'dots';
44+
45+
// Use shared progress calculation logic
46+
const currentStep = currentStepInfo.index + 1;
47+
let progressPercentage = calculateProgressPercentage( currentStep, steps.length, isDotStyle );
48+
49+
// Show 25% progress in "All steps" view for line style to preview the bar
50+
if ( ! isDotStyle && currentStepInfo.index === -1 && steps.length > 0 ) {
51+
progressPercentage = 25;
52+
}
53+
2454
return (
2555
<>
26-
<div className="jetpack-form-progress-indicator--wrapper">
27-
<div { ...blockProps }>
28-
<div className="jetpack-form-progress-indicator-bar" style={ progressBarStyle }></div>
56+
<InspectorControls group="color">
57+
<ColorGradientSettingsDropdown
58+
panelId={ clientId }
59+
settings={ [
60+
{
61+
colorValue: progressColor,
62+
onColorChange: color => setAttributes( { progressColor: color } ),
63+
label: __( 'Progress color', 'jetpack-forms' ),
64+
},
65+
{
66+
colorValue: progressBackgroundColor,
67+
onColorChange: color => setAttributes( { progressBackgroundColor: color } ),
68+
label: __( 'Track color', 'jetpack-forms' ),
69+
},
70+
] }
71+
{ ...colorGradientSettings }
72+
/>
73+
</InspectorControls>
74+
<div { ...blockProps }>
75+
<div className="jetpack-form-progress-indicator-steps">
76+
{ steps.map( ( step, index ) => {
77+
const isActive = index === currentStepInfo.index;
78+
const isCompleted = index < currentStepInfo.index;
79+
80+
return (
81+
<div
82+
key={ index }
83+
className={ clsx( 'jetpack-form-progress-indicator-step', {
84+
'is-active': isActive,
85+
'is-completed': isCompleted,
86+
} ) }
87+
data-step-index={ index }
88+
>
89+
<div className="jetpack-form-progress-indicator-line"></div>
90+
{ isDotStyle && (
91+
<div className="jetpack-form-progress-indicator-dot">
92+
<span className="jetpack-form-progress-indicator-step-number">
93+
{ isCompleted ? (
94+
<SVG
95+
width="24"
96+
height="24"
97+
viewBox="0 0 24 24"
98+
xmlns="http://www.w3.org/2000/svg"
99+
>
100+
<Path
101+
d="M16.7 7.1l-6.3 8.5-3.3-2.5-.9 1.2 4.5 3.4L17.9 8z"
102+
fill="currentColor"
103+
/>
104+
</SVG>
105+
) : (
106+
index + 1
107+
) }
108+
</span>
109+
</div>
110+
) }
111+
</div>
112+
);
113+
} ) }
114+
<div
115+
className="jetpack-form-progress-indicator-progress"
116+
style={ { width: `${ progressPercentage }%` } }
117+
></div>
29118
</div>
30119
</div>
31120
<StepControls formClientId={ parentFormId } showToggle={ false } showNavigation={ true } />

projects/packages/forms/src/blocks/form-progress-indicator/editor.scss

Lines changed: 0 additions & 29 deletions
This file was deleted.

0 commit comments

Comments
 (0)