-
Notifications
You must be signed in to change notification settings - Fork 67
Feat: More Guided Tours #3639
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Feat: More Guided Tours #3639
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,211 @@ | ||
| import { __ } from '@wordpress/i18n' | ||
| import { i18n } from 'stackable' | ||
| import { dispatch, select } from '@wordpress/data' | ||
| import { createInterpolateElement } from '@wordpress/element' | ||
|
|
||
| export const blockBackgrounds = { | ||
| initialize: () => { | ||
| // Add some default content that we will select | ||
|
|
||
| const blockObject = wp.blocks.createBlock( | ||
| 'stackable/columns', | ||
| { | ||
| uniqueId: '1dbe04e', | ||
| blockMargin: { bottom: '' }, | ||
| align: 'full', | ||
| containerWidth: 50, | ||
| containerHorizontalAlign: 'flex-start', | ||
| containerWidthUnit: '%', | ||
| }, | ||
| [ | ||
| wp.blocks.createBlock( | ||
| 'stackable/column', | ||
| { | ||
| uniqueId: 'f957abc', | ||
| columnSpacing: { | ||
| top: '', right: '', bottom: '', left: '', | ||
| }, | ||
| }, | ||
| [ | ||
| wp.blocks.createBlock( | ||
| 'stackable/heading', | ||
| { | ||
| uniqueId: 'a8ebea7', | ||
| // Retain our text | ||
| text: 'Explore the World with Us', | ||
| textTag: 'h2', | ||
| } | ||
| ), | ||
| wp.blocks.createBlock( | ||
| 'stackable/text', | ||
| { | ||
| uniqueId: '57e76a1', | ||
| // Retain our text | ||
| text: 'Discover breathtaking destinations, plan your next adventure, and make unforgettable memories with our travel guides and tips.', | ||
| } | ||
| ), | ||
| wp.blocks.createBlock( | ||
| 'stackable/button-group', | ||
| { uniqueId: 'e063798' }, | ||
| [ | ||
| wp.blocks.createBlock( | ||
| 'stackable/button', | ||
| { | ||
| uniqueId: '5d04ca8', | ||
| // Retain our text | ||
| text: 'Start your journey', | ||
| url: '', | ||
| } | ||
| ), | ||
| ] | ||
| ), | ||
| ] | ||
| ), | ||
| ] | ||
| ) | ||
| // Insert our block | ||
| dispatch( 'core/block-editor' ).insertBlocks( [ blockObject ], 0 ) | ||
|
|
||
| // Select the inner columns block for the tour | ||
| dispatch( 'core/block-editor' ).selectBlock( blockObject.clientId ) | ||
| }, | ||
| steps: [ | ||
| { | ||
| title: __( 'Discover Stackable Block Backgrounds & Containers', i18n ), | ||
| description: __( 'Welcome! Let\'s enhance your page by first adding a background to the Columns block. The Style Tab lets you tweak backgrounds, colors, borders, and typography for a custom look.', i18n ), | ||
| help: createInterpolateElement( __( 'Click the <strong>Style Tab</strong> in the sidebar to get started.', i18n ), { | ||
| strong: <strong />, | ||
| } ), | ||
| anchor: '.edit-post-sidebar__panel-tab.ugb-tab--style', | ||
| position: 'left', | ||
| glowTarget: '.edit-post-sidebar__panel-tab.ugb-tab--style', | ||
| nextEventTarget: '.edit-post-sidebar__panel-tab.ugb-tab--style', | ||
| preStep: () => { | ||
| // Open the inspector sidebar | ||
| dispatch( 'core/edit-post' ).openGeneralSidebar( 'edit-post/block' ) | ||
|
|
||
| // Look for the first "stackable/columns" block | ||
| const allBlocks = select( 'core/block-editor' ).getBlocks() | ||
| const columnsBlock = allBlocks.find( block => block.name === 'stackable/columns' ) | ||
| if ( columnsBlock ) { | ||
| dispatch( 'core/block-editor' ).selectBlock( columnsBlock.clientId ) | ||
| } | ||
| }, | ||
| postStep: () => { | ||
| // Click the tab | ||
| document.querySelector( '.edit-post-sidebar__panel-tab.ugb-tab--style:not(.is-active)' )?.click() | ||
| }, | ||
| }, | ||
| { | ||
| title: __( 'Enable a Block Background', i18n ), | ||
| description: __( 'Turn on the background option to instantly add a background layer to your section. Watch as your design transforms with a single toggle.', i18n ), | ||
| help: createInterpolateElement( __( 'Toggle ON the <strong>Background</strong> option to continue.', i18n ), { | ||
| strong: <strong />, | ||
| } ), | ||
| anchor: '.ugb-block-background-panel .components-panel__body-title', | ||
| position: 'left', | ||
| glowTarget: '.ugb-block-background-panel .components-panel__body-title', | ||
| nextEventTarget: '.ugb-block-background-panel .components-panel__body-title input[type="checkbox"]', | ||
| nextEvent: 'mousedown', | ||
| preStep: () => { | ||
| // Open the inspector sidebar | ||
| dispatch( 'core/edit-post' ).openGeneralSidebar( 'edit-post/block' ) | ||
|
|
||
| // Look for the first "stackable/columns" block | ||
| const allBlocks = select( 'core/block-editor' ).getBlocks() | ||
| const columnsBlock = allBlocks.find( block => block.name === 'stackable/columns' ) | ||
| if ( columnsBlock ) { | ||
| dispatch( 'core/block-editor' ).selectBlock( columnsBlock.clientId ) | ||
| } | ||
|
|
||
| setTimeout( () => { | ||
| // Click the tab | ||
| document.querySelector( '.edit-post-sidebar__panel-tab.ugb-tab--style:not(.is-active)' )?.click() | ||
| }, 100 ) | ||
|
Comment on lines
+121
to
+124
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chainRace conditions from hardcoded setTimeout delays. The 100ms delays are arbitrary and may fail on slower systems, during high CPU load, or in different browser environments, causing the tour to break or behave unpredictably. Consider using const waitForElement = (selector, timeout = 2000) => {
return new Promise((resolve, reject) => {
const startTime = Date.now()
const check = () => {
const element = document.querySelector(selector)
if (element) {
resolve(element)
} else if (Date.now() - startTime > timeout) {
reject(new Error(`Element ${selector} not found`))
} else {
requestAnimationFrame(check)
}
}
check()
})
}
// Usage in preStep:
await waitForElement('.edit-post-sidebar__panel-tab.ugb-tab--style')
document.querySelector('.edit-post-sidebar__panel-tab.ugb-tab--style:not(.is-active)')?.click()Also applies to: 184-186 I'll verify the review comment by examining the codebase and understanding the context around those hardcoded delays. 🏁 Script executed: #!/bin/bash
# Check if file exists and view the code around the mentioned lines
if [ -f "src/lazy-components/modal-tour/tours/block-backgrounds.js" ]; then
echo "=== File found. Showing lines 115-130 ==="
sed -n '115,130p' "src/lazy-components/modal-tour/tours/block-backgrounds.js"
echo ""
echo "=== Showing lines 180-190 ==="
sed -n '180,190p' "src/lazy-components/modal-tour/tours/block-backgrounds.js"
else
echo "File not found at expected path"
# Try to find it
find . -name "block-backgrounds.js" -type f 2>/dev/null
fiLength of output: 1368 🏁 Script executed: #!/bin/bash
# Search for all setTimeout calls in the file to understand usage patterns
echo "=== All setTimeout calls in block-backgrounds.js ==="
rg -n "setTimeout" "src/lazy-components/modal-tour/tours/block-backgrounds.js" -B2 -A4Length of output: 641 🏁 Script executed: #!/bin/bash
# Check if there are utility functions for DOM element waiting in the codebase
echo "=== Searching for existing waitFor, waitForElement patterns ==="
rg -n "waitFor|requestAnimationFrame" --type=js -g "!node_modules" | head -30Length of output: 299062 🏁 Script executed: #!/bin/bash
# Understand the structure and purpose of this file
echo "=== File context: imports, function definitions ==="
head -50 "src/lazy-components/modal-tour/tours/block-backgrounds.js"Length of output: 1372 Address race condition risk from hardcoded setTimeout delays in tour component. Lines 121-124 and 184-186 use arbitrary 100ms delays before querying and clicking DOM elements. On slower systems or under CPU load, the target elements may not exist in the DOM yet, causing the selector to return null and the tour to fail silently. Replace with polling or const waitForElement = (selector, timeout = 2000) => {
return new Promise((resolve, reject) => {
const startTime = Date.now()
const check = () => {
const element = document.querySelector(selector)
if (element) {
resolve(element)
} else if (Date.now() - startTime > timeout) {
reject(new Error(`Element ${selector} not found`))
} else {
requestAnimationFrame(check)
}
}
check()
})
}
// Usage in preStep:
await waitForElement('.edit-post-sidebar__panel-tab.ugb-tab--style:not(.is-active)')
document.querySelector('.edit-post-sidebar__panel-tab.ugb-tab--style:not(.is-active)')?.click()Also applies to: 184-186 🤖 Prompt for AI Agents |
||
| }, | ||
| }, | ||
| { | ||
| title: __( 'Customize the Background Color', i18n ), | ||
| description: __( 'Now let\'s personalize your section. Choose a background color to help your content stand out or integrate it seamlessly into your page design.', i18n ), | ||
| help: createInterpolateElement( __( 'Open the <strong>Background Color</strong> panel to select a color.', i18n ), { | ||
| strong: <strong />, | ||
| } ), | ||
| anchor: '.stk-color-palette-control', | ||
| position: 'left', | ||
| glowTarget: '.ugb-block-background-panel .block-editor-panel-color-gradient-settings__dropdown', | ||
| nextEventTarget: '.ugb-block-background-panel .block-editor-panel-color-gradient-settings__dropdown', | ||
| nextEvent: 'mousedown', | ||
| preStep: () => { | ||
| // Toggle background on | ||
| document.querySelector( '.ugb-block-background-panel:not(is-opened)' )?.click() | ||
| document.querySelector( '.ugb-block-background-panel .ugb-toggle-panel-form-toggle:not(is-checked) input' )?.click() | ||
| }, | ||
| postStep: () => { | ||
| // Click the tab | ||
| document.querySelector( '.ugb-block-background-panel .stk-color-palette-control .block-editor-panel-color-gradient-settings__dropdown:not(is-open)' )?.click() | ||
| }, | ||
| }, | ||
| { | ||
| title: __( 'Pick Your Brand Color', i18n ), | ||
| description: __( 'Select a color that matches your brand or mood. Try out different colors and instantly see the changes on your block.', i18n ), | ||
| help: createInterpolateElement( __( 'Choose a <strong>Color</strong> from the palette to apply it.', i18n ), { | ||
| strong: <strong />, | ||
| } ), | ||
| anchor: '.stk-color-palette-control__popover-content', | ||
| position: 'left', | ||
| glowTarget: '.stk-color-palette-control__popover-content', | ||
| nextEvent: 'mousedown', | ||
| nextEventTarget: '.stk-color-palette-control__popover-content *', | ||
| postStep: () => { | ||
| // Click the color picker | ||
| document.querySelector( '.ugb-block-background-panel .stk-color-palette-control .block-editor-panel-color-gradient-settings__dropdown.is-open' )?.click() | ||
| }, | ||
| }, | ||
| { | ||
| title: __( 'Add a Container for Better Layout', i18n ), | ||
| description: __( 'Turn on the Container option to give your columns content a background, padding, and improved alignment for a polished look.', i18n ), | ||
| help: createInterpolateElement( __( 'Toggle ON the <strong>Container</strong> to proceed.', i18n ), { | ||
| strong: <strong />, | ||
| } ), | ||
| anchor: '.ugb-panel--container-size .components-panel__body-title', | ||
| position: 'left', | ||
| glowTarget: '.ugb-panel--container-size .components-panel__body-title', | ||
| nextEventTarget: '.ugb-panel--container-size .components-panel__body-title input[type="checkbox"]', | ||
| nextEvent: 'mousedown', | ||
| preStep: () => { | ||
| // Click the tab | ||
| document.querySelector( '.ugb-block-background-panel .stk-color-palette-control .block-editor-panel-color-gradient-settings__dropdown.is-open' )?.click() | ||
|
|
||
| const allBlocks = select( 'core/block-editor' ).getBlocks() | ||
| const columnsBlock = allBlocks.find( block => block.name === 'stackable/columns' ) | ||
| if ( columnsBlock && columnsBlock.innerBlocks[ 0 ] ) { | ||
| dispatch( 'core/block-editor' ).selectBlock( columnsBlock.innerBlocks[ 0 ].clientId ) | ||
| document.querySelector( '.edit-post-sidebar__panel-tab.ugb-tab--layout:not(.is-active)' )?.click() | ||
| setTimeout( () => { | ||
| document.querySelector( '.ugb-panel--layout.is-opened .components-panel__body-title button' )?.click() | ||
| }, 100 ) | ||
| } | ||
| }, | ||
| }, | ||
| { | ||
| title: __( 'Block Backgrounds & Containers Recap', i18n ), | ||
| description: __( 'Great job! You\'ve learned how to add and customize block backgrounds and containers. These features are available in most Stackable blocks, helping you create beautiful, consistent layouts with ease.', i18n ), | ||
| preStep: () => { | ||
| // Toggle background on | ||
| document.querySelector( '.ugb-panel--container-size:not(is-opened)' )?.click() | ||
| document.querySelector( '.ugb-panel--container-size .ugb-toggle-panel-form-toggle:not(is-checked) input' )?.click() | ||
| }, | ||
| }, | ||
| { | ||
| title: __( 'Tip: Style All Blocks Efficiently', i18n ), | ||
| description: createInterpolateElement( __( 'Use the <strong>Stackable Design System</strong> to manage styles for all Stackable blocks globally. Perfect for a unified look and quick design changes!', i18n ), { | ||
| strong: <strong />, | ||
| } ), | ||
| anchor: '[aria-controls="stackable-global-settings:sidebar"]', | ||
| position: 'left-top', | ||
| offsetY: '-30px', | ||
| offsetX: '-8px', | ||
| glowTarget: '[aria-controls="stackable-global-settings:sidebar"]', | ||
| }, | ||
| ], | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,134 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { __ } from '@wordpress/i18n' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { i18n } from 'stackable' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { dispatch } from '@wordpress/data' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { createInterpolateElement } from '@wordpress/element' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export const hoverStates = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| initialize: () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Add some default content that we will select | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const blockObject = wp.blocks.createBlock( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'stackable/image', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| uniqueId: 'e063798', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| imageExternalUrl: 'https://picsum.photos/id/177/500/700.jpg', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+10
to
+16
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do not reuse hard-coded
Here is one way to do it: export const hoverStates = {
initialize: () => {
- // Add some default content that we will select
-
- const blockObject = wp.blocks.createBlock(
+ const makeUniqueId = ( prefix = 'tour-' ) => `${ prefix }${ Math.random().toString(36).slice(2, 11) }`
+ const blockObject = wp.blocks.createBlock(
'stackable/image',
{
- uniqueId: 'e063798',
+ uniqueId: makeUniqueId( 'hover-image-' ),📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Insert our block | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| dispatch( 'core/block-editor' ).insertBlocks( [ blockObject ], 0 ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Select the inner columns block for the tour | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| dispatch( 'core/block-editor' ).selectBlock( blockObject.clientId ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| setTimeout( () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| document.querySelector( '.edit-post-sidebar__panel-tab.ugb-tab--style:not(.is-active)' )?.click() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| setTimeout( () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| document.querySelector( '.ugb-panel--image:not(.is-opened)' )?.click() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const target = document.querySelector( '.stk-control:has([data-attribute="imageZoom"])' ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| target?.scrollIntoView( { behavior: 'auto', block: 'center' } ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, 100 ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, 200 ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+24
to
+31
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Replace brittle timeouts with deterministic waits. The nested A safer pattern could look like: - setTimeout( () => {
- document.querySelector( '.edit-post-sidebar__panel-tab.ugb-tab--style:not(.is-active)' )?.click()
- setTimeout( () => {
- document.querySelector( '.ugb-panel--image:not(.is-opened)' )?.click()
- const target = document.querySelector( '.stk-control:has([data-attribute="imageZoom"])' )
- target?.scrollIntoView( { behavior: 'auto', block: 'center' } )
- }, 100 )
- }, 200 )
+ const waitForElement = selector => new Promise( resolve => {
+ const tick = () => {
+ const node = document.querySelector( selector )
+ return node ? resolve( node ) : requestAnimationFrame( tick )
+ }
+ tick()
+ } )
+
+ waitForElement( '.edit-post-sidebar__panel-tab.ugb-tab--style' )
+ .then( tab => {
+ if ( ! tab.classList.contains( 'is-active' ) ) {
+ tab.click()
+ }
+ return waitForElement( '.ugb-panel--image' )
+ } )
+ .then( panel => {
+ if ( ! panel.classList.contains( 'is-opened' ) ) {
+ panel.click()
+ }
+ document
+ .querySelector( '.stk-control:has([data-attribute="imageZoom"])' )
+ ?.scrollIntoView( { behavior: 'auto', block: 'center' } )
+ } )📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| steps: [ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| title: __( 'Using the Hover Effect Controls', i18n ), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| description: createInterpolateElement( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| __( 'Locate the <strong>hover toggle</strong> next to <strong> Zoom</strong>. Click it to show the different hover state options.', i18n ), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { strong: <strong /> } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| anchor: '.stk-control:has([data-attribute="imageZoom"])', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| position: 'left', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| glowTarget: '.stk-control:has([data-attribute="imageZoom"]) .stk-control-label button[data-value="normal"]', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| nextEventTarget: '.stk-control:has([data-attribute="imageZoom"]) .stk-control-label button', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| title: __( 'Different Hover States', i18n ), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| description: createInterpolateElement( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| __( 'Now select the <strong>hover button</strong>. This lets you adjust how the image will look when hovered.', i18n ), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { strong: <strong /> } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| anchor: '.stk-control:has([data-attribute="imageZoom"]) .stk-label-unit-toggle__wrapper', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| position: 'left', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| glowTarget: '.stk-control:has([data-attribute="imageZoom"]) .stk-label-unit-toggle__wrapper', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| nextEventTarget: '.stk-control:has([data-attribute="imageZoom"]) .stk-label-unit-toggle__wrapper button:not(.is-active)[data-value="hover"]', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| nextEvent: 'mousedown', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| preStep: () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| document.querySelector( '.stk-control:has([data-attribute="imageZoom"]) .stk-label-unit-toggle__wrapper:not(.is-open) button' )?.click() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| postStep: () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| document.querySelector( '.stk-control:has([data-attribute="imageZoom"]) .stk-label-unit-toggle__wrapper button:not(.is-active)[data-value="hover"]' )?.click() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| title: __( 'Adjusting Zoom on Hover', i18n ), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| description: createInterpolateElement( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| __( 'The controls now affect the <strong>Hover</strong> state only. Try adjusting the <strong>Image Zoom</strong> value and see how the preview changes when hovered.', i18n ), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { strong: <strong /> } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| anchor: '.stk-control:has([data-attribute="imageZoom"])', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| position: 'left', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| glowTarget: '.stk-control:has([data-attribute="imageZoom"]) .stk-control-content', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| preStep: () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| document.querySelector( '.stk-control:has([data-attribute="imageZoom"]) .stk-label-unit-toggle__wrapper button:not(.is-active)[data-value="hover"]' )?.click() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| postStep: () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Update the order of the columns for mobile by dispatching an attribute update. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const allBlocks = wp.data.select( 'core/block-editor' ).getBlocks() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const imageBlock = allBlocks.find( block => block.name === 'stackable/image' ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if ( imageBlock && ! imageBlock.attributes?.imageZoomHover ) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| wp.data.dispatch( 'core/block-editor' ).updateBlockAttributes( imageBlock.clientId, { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| imageZoomHover: 1.5, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| title: __( 'Preview Your Hover Effect', i18n ), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| description: createInterpolateElement( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| __( 'The image on the canvas is now showing your <strong>new hover zoom effect</strong>. No need to hover—this view already reflects the hover state.', i18n ), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { strong: <strong /> } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| offsetX: '300px', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| title: __( 'Return to Normal State', i18n ), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| description: createInterpolateElement( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| __( 'Switch back to the normal state by clicking the <strong>cursor icon</strong> to test the hover effect in action.', i18n ), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { strong: <strong /> } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| anchor: '.stk-control:has([data-attribute="imageZoom"]) .stk-label-unit-toggle__wrapper button[data-value="normal"]', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| position: 'left', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| glowTarget: '.stk-control:has([data-attribute="imageZoom"]) .stk-label-unit-toggle__wrapper button[data-value="normal"]', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| nextEventTarget: '.stk-control:has([data-attribute="imageZoom"]) .stk-label-unit-toggle__wrapper button[data-value="normal"]', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| nextEvent: 'mousedown', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| preStep: () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| document.querySelector( '.stk-control:has([data-attribute="imageZoom"]) .stk-label-unit-toggle__wrapper:not(.is-open) button' )?.click() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| postStep: () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| document.querySelector( '.stk-control:has([data-attribute="imageZoom"]) .stk-label-unit-toggle__wrapper:not(.is-open) button' )?.click() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| setTimeout( () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| document.querySelector( '.stk-control:has([data-attribute="imageZoom"]) .stk-label-unit-toggle__wrapper button:not(.is-active)[data-value="normal"]' )?.click() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, 100 ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| title: __( 'Back on Normal State', i18n ), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| description: createInterpolateElement( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| __( 'You are now back on the <strong>normal</strong> state. Notice the hover toggle is <strong>yellow</strong> - that means a custom hover effect has been saved!', i18n ), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { strong: <strong /> } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| anchor: '.stk-control:has([data-attribute="imageZoom"]) .stk-control-label button', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| position: 'left', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| glowTarget: '.stk-control:has([data-attribute="imageZoom"]) .stk-control-label button', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| title: __( 'Pro Tip: Only Some Controls Feature Hover Toggle', i18n ), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| description: createInterpolateElement( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| __( 'Tip: Watch out—for some controls you <strong>won\'t see the hover state toggle</strong>. Only certain options support hover states. If you don\'t see the toggle, that control doesn\'t have hover customization!', i18n ), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { strong: <strong /> } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| offsetX: '300px', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Potential block ID conflicts with hardcoded uniqueIds.
The hardcoded
uniqueIdvalues (e.g.,'1dbe04e','f957abc') could conflict if blocks with these IDs already exist on the page, potentially causing unexpected behavior or errors.Consider generating unique IDs dynamically:
const blockObject = wp.blocks.createBlock( 'stackable/columns', { - uniqueId: '1dbe04e', + uniqueId: `tour-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,Or use a utility function if one exists in the codebase for generating unique block IDs.
🤖 Prompt for AI Agents