diff --git a/src/wp-admin/js/customize-controls.js b/src/wp-admin/js/customize-controls.js index c5cdfe9334..4a67e857aa 100644 --- a/src/wp-admin/js/customize-controls.js +++ b/src/wp-admin/js/customize-controls.js @@ -750,6 +750,57 @@ return equal; }; + /** + * Highlight the existence of a button. + * + * This function reminds the user of a button represented by the specified + * UI element, after an optional delay. If the user focuses the element + * before the delay passes, the reminder is canceled. + * + * @since 4.9.0 + * + * @param {jQuery} button - The element to highlight. + * @param {object} [options] - Options. + * @param {number} [options.delay=0] - Delay in milliseconds. + * @param {jQuery} [options.focusTarget] - A target for user focus that defaults to the highlighted element. + * If the user focuses the target before the delay passes, the reminder + * is canceled. This option exists to accommodate compound buttons + * containing auxiliary UI, such as the Publish button augmented with a + * Settings button. + * @returns {Function} An idempotent function that cancels the reminder. + */ + api.utils.highlightButton = function highlightButton( button, options ) { + var animationClass = 'button-see-me', + canceled = false, + params; + + params = _.extend( + { + delay: 0, + focusTarget: button + }, + options + ); + + function cancelReminder() { + canceled = true; + } + + // Remove animation class in case it was already applied. + button.removeClass( animationClass ); + + params.focusTarget.on( 'focusin', cancelReminder ); + setTimeout( function() { + params.focusTarget.off( 'focusin', cancelReminder ); + + if ( ! canceled ) { + button.addClass( animationClass ); + } + }, params.delay ); + + return cancelReminder; + }; + /** * Get current timestamp adjusted for server clock time. * diff --git a/src/wp-admin/js/customize-nav-menus.js b/src/wp-admin/js/customize-nav-menus.js index 31768861ad..cf7b9b1c2a 100644 --- a/src/wp-admin/js/customize-nav-menus.js +++ b/src/wp-admin/js/customize-nav-menus.js @@ -1142,6 +1142,22 @@ }; } api.Section.prototype.onChangeExpanded.call( section, expanded, args ); + }, + + /** + * Highlight how a user may create new menu items. + * + * This method reminds the user to create new menu items and how. + * It's exposed this way because this class knows best which UI needs + * highlighted but those expanding this section know more about why and + * when the affordance should be highlighted. + * + * @since 4.9.0 + * + * @returns {void} + */ + highlightNewItemButton: function() { + api.utils.highlightButton( this.contentContainer.find( '.add-new-menu-item' ), { delay: 2000 } ); } }); @@ -1325,6 +1341,7 @@ name = nameInput.val(), menuSection, customizeId, + editMenuSection, placeholderId = api.Menus.generatePlaceholderAutoIncrementId(); if ( ! name ) { @@ -1383,7 +1400,12 @@ wp.a11y.speak( api.Menus.data.l10n.menuAdded ); // Focus on the new menu section. - api.section( customizeId ).focus(); // @todo should we focus on the new menu's control and open the add-items panel? Thinking user flow... + editMenuSection = api.section( customizeId ); + editMenuSection.focus( { + completeCallback: function() { + editMenuSection.highlightNewItemButton(); + } + } ); // @todo should we focus on the new menu's control and open the add-items panel? Thinking user flow... }, /**