From 1964dde99a082b9e03e0e4989753da826fed6a8b Mon Sep 17 00:00:00 2001
From: Brandon Payton <brandon@happycode.net>
Date: Wed, 18 Oct 2017 09:54:41 +0200
Subject: [PATCH 1/2] Highlight New Items button for new menus

---
 src/wp-admin/js/customize-controls.js  | 48 ++++++++++++++++++++++++++++++++++
 src/wp-admin/js/customize-nav-menus.js | 21 ++++++++++++++-
 2 files changed, 68 insertions(+), 1 deletion(-)

diff --git a/src/wp-admin/js/customize-controls.js b/src/wp-admin/js/customize-controls.js
index c5cdfe9334..061b585cc4 100644
--- a/src/wp-admin/js/customize-controls.js
+++ b/src/wp-admin/js/customize-controls.js
@@ -750,6 +750,54 @@
 		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]
+	 * @param {number} [options.delay] 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,
+			delay,
+			focusTarget;
+
+		options = options || {};
+		delay = 'delay' in options ? options.delay : 0;
+		focusTarget = 'focusTarget' in options ? options.focusTarget : button;
+
+		function cancelReminder() {
+			canceled = true;
+		}
+
+		// Remove animation class in case it was already applied
+		button.removeClass( animationClass );
+
+		focusTarget.on( 'focusin', cancelReminder );
+		setTimeout( function() {
+			focusTarget.off( 'focusin', cancelReminder );
+
+			if ( ! canceled ) {
+				button.addClass( animationClass );
+			}
+		}, 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..a059aee569 100644
--- a/src/wp-admin/js/customize-nav-menus.js
+++ b/src/wp-admin/js/customize-nav-menus.js
@@ -1142,6 +1142,20 @@
 				};
 			}
 			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
+		 */
+		highlightNewItemAffordance: function () {
+			api.utils.highlightButton( this.contentContainer.find( '.add-new-menu-item' ), { delay: 2000 } );
 		}
 	});
 
@@ -1383,7 +1397,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...
+			var editMenuSection = api.section( customizeId );
+			editMenuSection.focus( {
+				completeCallback: function() {
+					editMenuSection.highlightNewItemAffordance();
+				}
+			} ); // @todo should we focus on the new menu's control and open the add-items panel? Thinking user flow...api.section( customizeId ).focus(); // @todo should we focus on the new menu's control and open the add-items panel? Thinking user flow...
 		},
 
 		/**
-- 
2.14.1


From e049a562d54f66133e188a0939e2923c199cfc4f Mon Sep 17 00:00:00 2001
From: Brandon Payton <brandon@happycode.net>
Date: Wed, 18 Oct 2017 17:45:52 +0200
Subject: [PATCH 2/2] Fix documentation style

---
 src/wp-admin/js/customize-controls.js | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/wp-admin/js/customize-controls.js b/src/wp-admin/js/customize-controls.js
index 061b585cc4..0dffe73916 100644
--- a/src/wp-admin/js/customize-controls.js
+++ b/src/wp-admin/js/customize-controls.js
@@ -763,10 +763,10 @@
 	 * @param {object} [options]
 	 * @param {number} [options.delay] Delay in milliseconds.
 	 * @param {jQuery} [options.focusTarget] A target for user focus that
-	 *	defaults to the highlighted element. If the user focuses the target
+	 * 	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.
+	 * 	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 ) {
@@ -783,7 +783,7 @@
 			canceled = true;
 		}
 
-		// Remove animation class in case it was already applied
+		// Remove animation class in case it was already applied.
 		button.removeClass( animationClass );
 
 		focusTarget.on( 'focusin', cancelReminder );
-- 
2.14.1

