Skip to content

Commit 695f1dd

Browse files
added prestep and poststep functions
1 parent e6e78ea commit 695f1dd

File tree

4 files changed

+129
-59
lines changed

4 files changed

+129
-59
lines changed

src/components/guided-modal-tour/editor.scss

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
.ugb-tour-modal--overlay {
2-
z-index: 1000001;
2+
z-index: 1000002;
33
background-color: transparent !important;
44
pointer-events: none;
55
}
@@ -24,10 +24,10 @@
2424
// Smoothly transition moving top & left.
2525
transition:
2626
max-width 0.4s cubic-bezier(0.4, 0, 0.2, 1),
27-
left 0.5s cubic-bezier(0.4, 0, 0.2, 1),
28-
top 0.5s cubic-bezier(0.4, 0, 0.2, 1),
29-
margin-left 0.5s cubic-bezier(0.4, 0, 0.2, 1),
30-
margin-top 0.5s cubic-bezier(0.4, 0, 0.2, 1),
27+
left 0.2s cubic-bezier(0.4, 0, 0.2, 1),
28+
top 0.2s cubic-bezier(0.4, 0, 0.2, 1),
29+
margin-left 0.2s cubic-bezier(0.4, 0, 0.2, 1),
30+
margin-top 0.2s cubic-bezier(0.4, 0, 0.2, 1),
3131
opacity 0.4s ease-in-out,
3232
transform 0.2s cubic-bezier(0.4, 0, 0.2, 1),
3333
box-shadow 0.2s ease-in-out;
@@ -163,13 +163,18 @@
163163

164164
.ugb-tour-modal__glow {
165165
position: absolute;
166-
z-index: 999999;
166+
z-index: 1000001;
167167
box-shadow: 0 0 20px #f00069;
168168
border-radius: 8px;
169169
pointer-events: none;
170170
animation: tour-modal-glow 0.7s infinite alternate;
171171
mix-blend-mode: multiply;
172172
will-change: transform, box-shadow;
173+
transition: opacity 0.2s ease-in-out;
174+
opacity: 1;
175+
&.ugb-tour-modal__glow--hidden {
176+
opacity: 0;
177+
}
173178
}
174179

175180
.ugb-tour-modal__glow--medium,

src/components/guided-modal-tour/index.js

Lines changed: 77 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ const ModalTour = props => {
8383
const [ isVisibleDelayed, setIsVisibleDelayed ] = useState( false )
8484
const [ forceRefresh, setForceRefresh ] = useState( 0 )
8585
const modalRef = useRef( null )
86+
const glowElementRef = useRef( null )
8687

8788
const {
8889
title,
@@ -99,15 +100,55 @@ const ModalTour = props => {
99100
nextEventTarget = null, // If provided, this is a selector for the element to trigger the next event if there is one.
100101
nextEvent = 'click', // This is the event to listen for to trigger the next step.
101102
glowTarget = null, // If provided, this is a selector for the element to glow when the step is active.
103+
// eslint-disable-next-line no-unused-vars
104+
preStep = NOOP, // If provided, this is a function to run before the step is shown.
105+
// eslint-disable-next-line no-unused-vars
106+
postStep = NOOP, // If provided, this is a function to run after the step is shown.
102107
} = steps[ currentStep ]
103108

109+
// While the modal is visible, just keep on force refreshing the modal in an interval to make sure the modal is always in the correct position.
110+
useEffect( () => {
111+
let interval
112+
if ( isVisible ) {
113+
interval = setInterval( () => {
114+
setForceRefresh( forceRefresh => forceRefresh + 1 )
115+
}, 300 )
116+
}
117+
return () => clearInterval( interval )
118+
}, [ isVisible, isVisibleDelayed ] )
119+
104120
// Create a stable function reference for the event listener
105121
const handleNextEvent = useCallback( () => {
106-
setCurrentStep( currentStep + 1 )
122+
setCurrentStep( currentStep => {
123+
setTimeout( () => {
124+
steps[ currentStep ]?.postStep?.( currentStep )
125+
}, 50 )
126+
const nextStep = currentStep + 1
127+
steps[ nextStep ]?.preStep?.( nextStep )
128+
return nextStep
129+
} )
130+
setTimeout( () => {
131+
setForceRefresh( forceRefresh => forceRefresh + 1 )
132+
}, 50 )
107133
setTimeout( () => {
108-
setForceRefresh( forceRefresh + 1 )
134+
setForceRefresh( forceRefresh => forceRefresh + 1 )
135+
}, 350 )
136+
}, [ currentStep, steps ] )
137+
138+
const handleBackEvent = useCallback( () => {
139+
setCurrentStep( currentStep => {
140+
// steps[ currentStep ]?.postStep?.( currentStep )
141+
const nextStep = currentStep - 1
142+
steps[ nextStep ]?.preStep?.( nextStep )
143+
return nextStep
144+
} )
145+
setTimeout( () => {
146+
setForceRefresh( forceRefresh => forceRefresh + 1 )
109147
}, 50 )
110-
}, [ currentStep ] )
148+
setTimeout( () => {
149+
setForceRefresh( forceRefresh => forceRefresh + 1 )
150+
}, 350 )
151+
}, [ currentStep, steps ] )
111152

112153
// Show modal after 1 second delay
113154
useEffect( () => {
@@ -116,7 +157,7 @@ const ModalTour = props => {
116157
setTimeout( () => {
117158
setIsVisibleDelayed( true )
118159
}, 150 )
119-
}, 1500 )
160+
}, 1050 )
120161

121162
return () => clearTimeout( timer )
122163
}, [] )
@@ -162,6 +203,22 @@ const ModalTour = props => {
162203
}
163204
}, [ currentStep, nextEventTarget, nextEvent, handleNextEvent ] )
164205

206+
// Create the glow element while this component is mounted.
207+
useEffect( () => {
208+
// Create the element.
209+
const element = document.createElement( 'div' )
210+
element.className = `ugb-tour-modal__glow ugb-tour-modal__glow--hidden`
211+
document.body.appendChild( element )
212+
213+
// Keep track of the element.
214+
glowElementRef.current = element
215+
216+
return () => {
217+
glowElementRef.current = null
218+
element.remove()
219+
}
220+
}, [] )
221+
165222
// These are the X and Y offsets of the modal relative to the anchor. This will be
166223
const [ modalOffsetX, modalOffsetY ] = useMemo( () => {
167224
if ( ! modalRef.current ) {
@@ -179,6 +236,10 @@ const ModalTour = props => {
179236
// We have the modalRef.current which we can use to get the modal's bounding client rect.
180237
const anchorRect = document.querySelector( anchor )?.getBoundingClientRect()
181238

239+
if ( ! anchorRect ) {
240+
return defaultOffset
241+
}
242+
182243
switch ( position ) {
183244
case 'left':
184245
// Left, middle
@@ -216,21 +277,16 @@ const ModalTour = props => {
216277
: 'small'
217278

218279
// Create the element.
219-
const element = document.createElement( 'div' )
220-
element.className = `ugb-tour-modal__glow ugb-tour-modal__glow--${ glowTargetSize }`
221-
element.style.top = `${ targetRect.top - 8 }px`
222-
element.style.left = `${ targetRect.left - 8 }px`
223-
element.style.width = `${ targetRect.width + 16 }px`
224-
element.style.height = `${ targetRect.height + 16 }px`
225-
document.body.appendChild( element )
226-
}
227-
}
228-
// Remove the element when the component unmounts or the step changes.
229-
return () => {
230-
if ( glowTarget ) {
231-
const element = document.querySelector( '.ugb-tour-modal__glow' )
232-
element?.remove()
280+
if ( glowElementRef.current ) {
281+
glowElementRef.current.className = `ugb-tour-modal__glow ugb-tour-modal__glow--${ glowTargetSize }`
282+
glowElementRef.current.style.top = `${ targetRect.top - 8 }px`
283+
glowElementRef.current.style.left = `${ targetRect.left - 8 }px`
284+
glowElementRef.current.style.width = `${ targetRect.width + 16 }px`
285+
glowElementRef.current.style.height = `${ targetRect.height + 16 }px`
286+
}
233287
}
288+
} else if ( glowElementRef.current ) {
289+
glowElementRef.current.className = `ugb-tour-modal__glow ugb-tour-modal__glow--hidden`
234290
}
235291
}, [ glowTarget, currentStep, isVisible, isVisibleDelayed, forceRefresh ] )
236292

@@ -270,10 +326,7 @@ const ModalTour = props => {
270326
<Button
271327
onClick={ () => {
272328
ctaOnClick()
273-
setCurrentStep( currentStep + 1 )
274-
setTimeout( () => {
275-
setForceRefresh( forceRefresh + 1 )
276-
}, 50 )
329+
handleNextEvent()
277330
} }
278331
variant="primary"
279332
className="ugb-tour-modal__cta"
@@ -285,17 +338,11 @@ const ModalTour = props => {
285338
<Steps
286339
numSteps={ steps.length }
287340
currentStep={ currentStep }
288-
onClickStep={ setCurrentStep }
289341
/>
290342
{ currentStep > 0 && (
291343
<Button
292344
variant="tertiary"
293-
onClick={ () => {
294-
setCurrentStep( currentStep - 1 )
295-
setTimeout( () => {
296-
setForceRefresh( forceRefresh + 1 )
297-
}, 50 )
298-
} }
345+
onClick={ handleBackEvent }
299346
>
300347
<Icon icon={ arrowLeft } size={ 20 } />
301348
&nbsp;
@@ -337,10 +384,7 @@ const ModalTour = props => {
337384
}
338385
onClose()
339386
} else {
340-
setCurrentStep( currentStep + 1 )
341-
setTimeout( () => {
342-
setForceRefresh( forceRefresh + 1 )
343-
}, 100 )
387+
handleNextEvent()
344388
}
345389
} }
346390
>
@@ -364,7 +408,6 @@ const Steps = props => {
364408
const {
365409
numSteps = 3,
366410
currentStep = 0,
367-
// onClickStep = NOOP,
368411
} = props
369412

370413
if ( numSteps === 1 ) {
@@ -382,7 +425,6 @@ const Steps = props => {
382425
return (
383426
<div
384427
className={ classes }
385-
// onClick={ () => onClickStep( index ) }
386428
key={ index }
387429
/>
388430
)

src/components/guided-modal-tour/tour-steps.js

Lines changed: 40 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,22 @@ export const TOUR_STEPS = {
5151
steps: [
5252
{
5353
title: '👋 ' + __( 'Welcome to Your Design System', i18n ),
54-
description: __( 'We\'re excited to have you here. Let\'s get you started by opening the Design Library. Click the button above to get started.', i18n ),
54+
description: __( 'Design once, apply everywhere! Set global styles so every block across your site looks and feels unified.', i18n ),
5555
size: 'medium',
5656
anchor: '.interface-interface-skeleton__sidebar',
5757
position: 'left',
58-
// nextEventTarget: '.ugb-insert-library-button',
59-
glowTarget: '.interface-interface-skeleton__sidebar',
60-
// showNext: false,
58+
// glowTarget: '.interface-interface-skeleton__sidebar',
59+
},
60+
{
61+
title: __( 'Use The Style Guide', i18n ),
62+
description: __( 'You can use the Style Guide to see how your complete design system looks.', i18n ),
63+
help: createInterpolateElement( __( 'Click the <strong>Style Guide</strong> button to continue.', i18n ), {
64+
strong: <strong />,
65+
} ),
66+
anchor: '.ugb-modal-design-system__style-guide-button',
67+
position: 'left',
68+
nextEventTarget: '.ugb-modal-design-system__style-guide-button',
69+
glowTarget: '.ugb-modal-design-system__style-guide-button',
6170
},
6271
],
6372
},
@@ -100,33 +109,47 @@ export const TOUR_STEPS = {
100109
nextEventTarget: '.ugb-design-library-item',
101110
offsetX: '-400px',
102111
},
103-
{
104-
title: __( 'You Can Add More Than One', i18n ),
105-
description: __( 'You can add more than one designs to your page. When you\'re done, you can the Add Designs button to insert. But let\'s see what else you can do.', i18n ),
106-
size: 'small',
107-
offsetX: '-400px',
108-
},
109112
{
110113
title: __( 'Pick Styling Options', i18n ),
111-
description: __( 'Turn on backgrounds, change color schemes, to customize the library in real-time.', i18n ),
114+
description: __( 'Optionally, you can turn on backgrounds, change color schemes, to customize the library in real-time.', i18n ),
112115
help: createInterpolateElement( __( 'Toggle the <strong>Section Background</strong> to continue.', i18n ), {
113116
strong: <strong />,
114117
} ),
115118
anchor: '.ugb-modal-design-library__enable-background',
116119
position: 'right',
117120
nextEventTarget: '.ugb-modal-design-library__enable-background',
118121
glowTarget: '.ugb-modal-design-library__enable-background',
122+
postStep: () => {
123+
const el = document.querySelector( '.ugb-modal-design-library__enable-background input' )
124+
// If the input is not checked, click the button.
125+
if ( ! el.checked ) {
126+
el.click()
127+
}
128+
},
119129
},
120130
{
121-
title: __( 'Designs are Styled', i18n ),
122-
description: __( 'Great! Your entire library now has a background. You can also change the other styling options next time.', i18n ),
123-
anchor: '.ugb-modal-design-library__designs',
124-
position: 'left',
125-
offsetX: '200px',
131+
title: __( 'Change Color Schemes', i18n ),
132+
description: __( 'Awesome! Your designs now have a background. Try out the available color schemes below. You can also create your own later!', i18n ),
133+
help: createInterpolateElement( __( 'Pick a <strong>Color Scheme</strong> to continue.', i18n ), {
134+
strong: <strong />,
135+
} ),
136+
anchor: '.ugb-design-library__color-scheme-popover',
137+
position: 'top',
138+
nextEventTarget: '.ugb-design-library__color-scheme-popover .ugb-modal-design-library__stk-color-scheme',
139+
glowTarget: '.ugb-design-library__color-scheme-popover .ugb-modal-design-library__stk-color-scheme:last-of-type',
140+
preStep: () => {
141+
// Let's make sure the background scheme is open.
142+
if ( ! document.querySelector( '.ugb-design-library__color-scheme-popover' ) ) {
143+
document.querySelector( '.ugb-modal-design-library__background-scheme .ugb-modal-design-library__stk-color-scheme' )?.click()
144+
}
145+
},
146+
postStep: () => {
147+
document.querySelector( '.ugb-design-library__color-scheme-popover .ugb-modal-design-library__stk-color-scheme:last-of-type' )?.click()
148+
},
126149
},
127150
{
128151
title: __( 'Patterns and Full-Pages', i18n ),
129-
description: __( 'Aside from patterns, there are also full-page layouts in the library.', i18n ),
152+
description: __( 'Great! Your entire library is now styled. Aside from patterns, there are also full-page layouts in the library.', i18n ),
130153
help: createInterpolateElement( __( 'Click the <strong>Pages</strong> tab to continue.', i18n ), {
131154
strong: <strong />,
132155
} ),

src/components/modal-design-library/modal.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ export const ModalDesignLibrary = props => {
253253
/>
254254
<BaseControl
255255
label={ __( 'Background Scheme', i18n ) }
256-
className="ugb-modal-design-library__color-scheme-label"
256+
className="ugb-modal-design-library__color-scheme-label ugb-modal-design-library__background-scheme"
257257
>
258258
<Dropdown
259259
className="ugb-modal-design-library__color-scheme-dropdown"

0 commit comments

Comments
 (0)