Repository: adobecom/milo
Pull request #4092: Adding arrow Up/Down navigation for localnav
Author: login: bandana147
Labels: name: verified
description: PR has been E2E tested by a reviewer
name: Ready for Stage
Created: 2025-05-07T09:34:41Z | Merged: 2025-05-19T13:55:27Z

<!-- Before submitting, please review all open PRs. -->

* Adding arrow Up/Down navigation for localnav items
* Localnav will open on arrow down
* If the focus is on last item when pressed arrow down the focus will go to localnav header

Resolves: [MWPW-164678](https://jira.corp.adobe.com/browse/MWPW-164678)

**Test URLs:**
- Before: https://main--milo--adobecom.aem.page/?martech=off
- After: https://localnav-arrow--milo--adobecom.aem.page/?martech=off

QA: https://main--cc--adobecom.hlx.live/jp/creativecloud?milolibs=localnav-arrow


## GNav Test URLs

**Gnav + Footer + Region Picker modal:**
- Acrobat: https://main--dc--adobecom.hlx.live/acrobat?martech=off&milolibs=localnav-arrow--milo--adobecom
- BACOM: https://main--bacom--adobecom.hlx.live/?martech=off&milolibs=localnav-arrow--milo--adobecom
- CC: https://main--cc--adobecom.aem.live/creativecloud?martech=off&milolibs=localnav-arrow--milo--adobecom
- Milo: https://localnav-arrow--milo--adobecom.aem.page/drafts/blaishram/test-urls/page?martech=off
- Express: https://main--express-milo--adobecom.aem.live/express/?martech=off&milolibs=localnav-arrow--milo--adobecom
- News: https://main--news--adobecom.aem.live/?martech=off&milolibs=localnav-arrow--milo--adobecom
- Homepage: https://main--homepage--adobecom.aem.live/homepage/index-loggedout?martech=off&milolibs=localnav-arrow--milo--adobecom

**Thin Gnav + ThinFooter + Region Picker dropup:**
- Acrobat: https://main--dc--adobecom.hlx.page/drafts/blaishram/test-urls/page-gnav-footer-thin?martech=off&milolibs=localnav-arrow--milo--adobecom
- BACOM: https://main--bacom--adobecom.hlx.page/drafts/blaishram/test-urls/page-gnav-footer-thin?martech=off&milolibs=localnav-arrow--milo--adobecom
- CC: https://main--cc--adobecom.hlx.page/drafts/blaishram/test-urls/page-gnav-footer-thin?martech=off&milolibs=localnav-arrow--milo--adobecom
- Milo: https://localnav-arrow--milo--adobecom.hlx.page/drafts/blaishram/test-urls/page-gnav-footer-thin?martech=off
- Express: https://main--express-milo--adobecom.hlx.page/drafts/blaishram/test-urls/page-gnav-footer-thin?martech=off&milolibs=localnav-arrow--milo--adobecom
- News: https://main--news--adobecom.hlx.page/drafts/blaishram/test-urls/page-gnav-footer-thin?martech=off&milolibs=localnav-arrow--milo--adobecom
- Homepage: https://main--homepage--adobecom.hlx.page/drafts/blaishram/test-urls/page-gnav-footer-thin?martech=off&milolibs=localnav-arrow--milo--adobecom

**Localnav + Promo:**
- Acrobat: https://main--dc--adobecom.hlx.page/drafts/blaishram/test-urls/page-with-promo?martech=off&milolibs=localnav-arrow--milo--adobecom
- BACOM: https://main--bacom--adobecom.hlx.page/drafts/blaishram/test-urls/page-with-promo?martech=off&milolibs=localnav-arrow--milo--adobecom
- CC: https://main--cc--adobecom.hlx.page/drafts/blaishram/test-urls/page-with-promo?martech=off&milolibs=localnav-arrow--milo--adobecom
- Milo: https://localnav-arrow--milo--adobecom.hlx.page/drafts/blaishram/test-urls/page-with-promo?martech=off
- Express: https://main--express-milo--adobecom.hlx.page/drafts/blaishram/test-urls/page-with-promo?martech=off&milolibs=localnav-arrow--milo--adobecom
- News: https://main--news--adobecom.hlx.page/drafts/blaishram/test-urls/page-with-promo?martech=off&milolibs=localnav-arrow--milo--adobecom
- Homepage: https://main--homepage--adobecom.hlx.page/drafts/blaishram/test-urls/page-with-promo?martech=off&milolibs=localnav-arrow--milo--adobecom

**Sticky Branch Banner:**
- URL: https://main--federal--adobecom.aem.page/drafts/blaishram/banner/branch-banner-sticky?martech=off&milolibs=localnav-arrow--milo--adobecom
**Inline Branch Banner:**
- URL: https://main--federal--adobecom.aem.page/drafts/blaishram/banner/branch-banner-inline?martech=off&milolibs=localnav-arrow--milo--adobecom

**Blog**
- URL: https://main--blog--adobecom.aem.page/?martech=off&milolibs=localnav-arrow--milo--adobecom

**RTL Locale**
- URL: https://main--homepage--adobecom.aem.live/mena_ar/homepage/index-loggedout?martech=off&milolibs=localnav-arrow--milo--adobecom


Diff:
diff --git a/libs/blocks/global-navigation/global-navigation.js b/libs/blocks/global-navigation/global-navigation.js
index 2436c265087..a956af8de87 100644
--- a/libs/blocks/global-navigation/global-navigation.js
+++ b/libs/blocks/global-navigation/global-navigation.js
@@ -510,11 +510,25 @@ class Gnav {
       this.block.after(localNav);
     }
     localNav.setAttribute('daa-lh', `${title}_localNav`);
-    localNav.append(toFragment`<button class="feds-navLink--hoverCaret feds-localnav-title" aria-haspopup="true" aria-expanded="false" daa-ll="${title}_localNav|open"></button>`, toFragment` <div class="feds-localnav-curtain"></div>`, toFragment` <div class="feds-localnav-items"></div>`, toFragment`<a href="#" class="feds-sr-only feds-localnav-exit">.</a>`);
+    const localNavBtn = toFragment`<button class="feds-navLink--hoverCaret feds-localnav-title" aria-haspopup="true" aria-expanded="false" daa-ll="${title}_localNav|open"></button>`;
+    const localNavCurtain = toFragment` <div class="feds-localnav-curtain"></div>`;
+    // Skip keyboard navigation on localnav items if it is closed
+    localNav.append(localNavBtn, localNavCurtain, toFragment` <div class="feds-localnav-items"></div>`, toFragment`<a href="#" class="feds-sr-only feds-localnav-exit">.</a>`);
 
     const itemWrapper = localNav.querySelector('.feds-localnav-items');
-    const titleLabel = await replaceKey('overview', getFedsPlaceholderConfig());
+    const localNavTitle = document.querySelector('.feds-localnav-title');
+    // Skip keyboard navigation on localnav items if it is closed
+    const observer = new MutationObserver(() => {
+      const isExpanded = localNavTitle.getAttribute('aria-expanded') === 'true';
+      itemWrapper.toggleAttribute('aria-hidden', !isExpanded);
+      [...itemWrapper.childNodes].forEach((node) => {
+        node.querySelector('a, button').toggleAttribute('aria-hidden', !isExpanded);
+        node.querySelector('a, button').setAttribute('tabindex', isExpanded ? '0' : '-1');
+      });
+    });
+    observer.observe(localNavTitle, { attributes: true, attributeFilter: ['aria-expanded'] });
 
+    const titleLabel = await replaceKey('overview', getFedsPlaceholderConfig());
     localNavItems.forEach((elem, idx) => {
       const clonedItem = elem.cloneNode(true);
       const link = clonedItem.querySelector('a, button');
@@ -1230,6 +1244,8 @@ class Gnav {
       const elements = [...document.querySelectorAll('.feds-localnav .feds-navItem')].find(
         (el) => {
           const link = el.querySelector('a, button');
+          link.setAttribute('tabindex', '-1');
+          link.setAttribute('aria-hidden', true);
           return link.dataset.title?.trim() === navItem.textContent;
         },
       );
diff --git a/libs/blocks/global-navigation/utilities/keyboard/localNav.js b/libs/blocks/global-navigation/utilities/keyboard/localNav.js
index ae05882e8b7..29f9696c998 100644
--- a/libs/blocks/global-navigation/utilities/keyboard/localNav.js
+++ b/libs/blocks/global-navigation/utilities/keyboard/localNav.js
@@ -1,6 +1,90 @@
-import { selectors } from './utils.js';
+import { selectors, getNextVisibleItemPosition, getPreviousVisibleItemPosition } from './utils.js';
 import { trigger } from '../utilities.js';
 
+const focusables = (root) => [...root.querySelectorAll('a[href],button:not([disabled])')];
+
+const nestedFocusables = (root) => [...root.querySelectorAll('a, button, .feds-menu-headline')].filter((el) => {
+  const items = el.closest('.feds-menu-items');
+  const headline = items?.previousElementSibling;
+  return !items || headline?.getAttribute('aria-expanded') === 'true';
+});
+
+function getNavList() {
+  return [...document.querySelector('.feds-localnav-items').children].flatMap((item) => {
+    const triggerBtn = item.querySelector('a, button, .feds-menu-headline');
+    if (!triggerBtn || !triggerBtn.matches('[aria-haspopup="true"][aria-expanded="true"]')) return triggerBtn ? [triggerBtn] : [];
+
+    const popup = item.querySelector('.feds-popup');
+    if (!popup) return [triggerBtn];
+
+    const hasHeadline = item.querySelector('.feds-menu-items');
+    const dropdown = hasHeadline
+      ? nestedFocusables(popup)
+      : focusables(popup);
+
+    return [triggerBtn, ...dropdown];
+  });
+}
+
+function getState() {
+  const items = [...document.querySelectorAll(selectors.localNavItems)];
+  const openTrigger = document.querySelector(selectors.expandedPopupTrigger);
+  const currentEl = document.activeElement
+    .closest(selectors.localNavItem)?.querySelector(selectors.localNavItems);
+  const curr = items.indexOf(currentEl);
+  return {
+    items,
+    curr,
+    prev: getPreviousVisibleItemPosition(curr, items),
+    next: getNextVisibleItemPosition(curr, items),
+    openTrigger,
+  };
+}
+
+function open({ triggerEl, e } = {}) {
+  const { items, curr } = getState();
+  const el = triggerEl || items[curr];
+  if (!el?.hasAttribute('aria-haspopup')) return;
+  if (e) e.preventDefault();
+  if (el.getAttribute('aria-expanded') === 'false') {
+    const isHeader = el.classList.contains('feds-localnav-title') || el.classList.contains('feds-menu-headline');
+    if (isHeader) document.querySelector(selectors.localNav).classList.add('feds-localnav--active');
+    trigger({ element: el, type: isHeader ? 'headline' : 'localNavItem' });
+  }
+}
+
+function navigate(current, dir) {
+  const items = getNavList();
+  const currIdx = items.indexOf(current);
+  const isHeader = current.classList.contains('feds-localnav-title');
+  const titleBtn = document.querySelector(`${selectors.localNav} > button`);
+  if (currIdx === -1 && !isHeader) return;
+  if (isHeader && dir === 1) open({ triggerEl: current });
+  // If item is first or last move next focus to header
+  if ((dir === 1 && current === items.at(-1)) || (dir === -1 && current === items.at(0))) {
+    titleBtn?.focus();
+    return;
+  }
+  // if Arrow up on header element focus to its last item
+  if (dir === -1 && isHeader) {
+    items.at(-1)?.focus();
+    return;
+  }
+  const next = items[(currIdx + dir + items.length) % items.length];
+  next.focus();
+
+  if (next.matches('[aria-haspopup="true"]')) {
+    const collapsed = next.matches('[aria-expanded="false"]');
+    open({ triggerEl: next });
+    // Focus on last item of the dropdown if arrow up
+    if (dir === -1 && collapsed) {
+      const hasHeadline = next.parentElement.querySelector('.feds-menu-items');
+      const dropdownItems = hasHeadline ? nestedFocusables(next.parentElement) : focusables(next.parentElement.querySelector('.feds-popup'));
+      dropdownItems.at(-1)?.focus();
+    }
+  }
+}
+
 class LocalNavItem {
   constructor() {
     this.localNav = document.querySelector(selectors.localNav);
@@ -15,9 +99,12 @@ class LocalNavItem {
     switch (code) {
       case 'Space':
       case 'Enter':
+        e.stopPropagation();
+        e.preventDefault();
         if (isHeadline) {
-          e.preventDefault(); // Prevent default scrolling behavior for Space key
           trigger({ element: target, event: e, type: 'headline' });
+        } else {
+          e.target.click();
         }
         break;
       case 'Escape': // close on escape
@@ -27,6 +114,14 @@ class LocalNavItem {
           this.localNavTrigger?.focus();
         }
         break;
+      case 'ArrowDown':
+      case 'ArrowUp': {
+        e.stopPropagation();
+        e.preventDefault();
+        const dir = code === 'ArrowDown' ? +1 : -1;
+        navigate(target, dir);
+        break;
+      }
       default:
         break;
     }
diff --git a/libs/blocks/global-navigation/utilities/keyboard/utils.js b/libs/blocks/global-navigation/utilities/keyboard/utils.js
index a198af51c1b..46917a8cf22 100644
--- a/libs/blocks/global-navigation/utilities/keyboard/utils.js
+++ b/libs/blocks/global-navigation/utilities/keyboard/utils.js
@@ -46,6 +46,8 @@ const selectors = {
   localNavActive: '.feds-localnav--active',
   localNavTitle: '.feds-localnav-title',
   localNavExit: '.feds-localnav-exit',
+  localNavItem: '.feds-localnav-items .feds-navItem',
+  localNavItems: '.feds-navItem .feds-menu-column > a, .feds-navItem > a, .feds-navItem > button, .feds-navItem > .feds-cta-wrapper > .feds-cta',
 };
 
 selectors.profileDropdown = `


Reviews:
user: login: sharmrj
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-08T06:44:09Z
user: login: Deva309
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-08T08:11:44Z
user: login: sonawanesnehal3
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-08T09:51:28Z
user: login: sharmrj
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-09T09:06:26Z

Review comments:
diff_hunk: @@ -506,15 +506,22 @@ class Gnav {
         tags: 'gnav',
         errorType: 'info',
       });
-      localNav = toFragment`<div class="feds-localnav"/>`;
+      localNav = toFragment`<div class="feds-localnav" aria-hidden="true"/>`;
       this.block.after(localNav);
     }
     localNav.setAttribute('daa-lh', `${title}_localNav`);
-    localNav.append(toFragment`<button class="feds-navLink--hoverCaret feds-localnav-title" aria-haspopup="true" aria-expanded="false" daa-ll="${title}_localNav|open"></button>`, toFragment` <div class="feds-localnav-curtain"></div>`, toFragment` <div class="feds-localnav-items"></div>`, toFragment`<a href="#" class="feds-sr-only feds-localnav-exit">.</a>`);
+    localNav.append(toFragment`<button class="feds-navLink--hoverCaret feds-localnav-title" aria-haspopup="true" aria-expanded="false" daa-ll="${title}_localNav|open"></button>`, toFragment` <div class="feds-localnav-curtain"></div>`, toFragment` <div class="feds-localnav-items" inert></div>`, toFragment`<a href="#" class="feds-sr-only feds-localnav-exit">.</a>`);
path: libs/blocks/global-navigation/global-navigation.js
user: login: sharmrj
body: I think we might want to bind each of these `toFragment`s to a descriptive name.
created_at: 2025-05-09T09:06:26Z
author_association: CONTRIBUTOR

PR comments:
user: login: aem-code-sync[bot]
created_at: 2025-05-07T09:34:45Z
body: <!-- aem-bot-dash -->
Hello, I'm the AEM Code Sync Bot and I will run some actions to deploy your branch and validate page speed.
In case there are problems, just click a checkbox below to rerun the respective action.

- [ ] <!-- action-psi --> Re-run PSI checks
- [ ] <!-- action-sync --> Re-sync branch

<details>
<summary>Commits</summary>
<!-- commit-history -->

* [f203835](https://github.com/adobecom/milo/commit/f203835815546739d6aee7a96d910e089f4644cf) :white_check_mark: (latest)
* [7f46abf](https://github.com/adobecom/milo/commit/7f46abfd8c0b0b50eb333b2af161534dcbd34bac) :white_check_mark:
* [6e4a35c](https://github.com/adobecom/milo/commit/6e4a35c54bbbc49f02cdebab02dd622b4ad4ed45) :white_check_mark:
* [bdc3d97](https://github.com/adobecom/milo/commit/bdc3d97604ca900822ef1d4f3fdceabcb9a327d0) :white_check_mark:
* [88a1725](https://github.com/adobecom/milo/commit/88a1725dc429ba416f279eb6a39bee6fd218335d) :white_check_mark:
* [3ab8be6](https://github.com/adobecom/milo/commit/3ab8be61b5f6acfa0660db7feeb5cd080b107140) :white_check_mark:
* [7379418](https://github.com/adobecom/milo/commit/73794180b90403ef7f46461a313e701154480d5c) :white_check_mark:
* [d3bf841](https://github.com/adobecom/milo/commit/d3bf841097d2ee3057c5d47effbeabf1f50689b2) :white_check_mark:
* [3be5a1c](https://github.com/adobecom/milo/commit/3be5a1c334ea7b73b24949c1f36bebfc693a08fa) :white_check_mark:
* [dc87d99](https://github.com/adobecom/milo/commit/dc87d994432f0a38f8b2275724f9c2c2a2b13fc2) :white_check_mark:

<!-- commit-history-end -->
</details>
author_association: CONTRIBUTOR
user: login: aem-code-sync[bot]
created_at: 2025-05-07T09:35:08Z
body: <!-- aem-bot-psi -->
| | Page | Scores | Audits | Google |
|-|------|--------|--------|--------|
| :iphone: | [/?martech=off](https://localnav-arrow--milo--adobecom.aem.page/?martech=off) | [![PERFORMANCE](https://img.shields.io/badge/PERFORMANCE-97-green?style=for-the-badge "Performance")](https://googlechrome.github.io/lighthouse/scorecalc/#device=mobile&version=12.6.0&SI=4531.608367998838&FCP=849&LCP=1834.353085&TBT=0&CLS=0 "See Calculator") ![A11Y](https://img.shields.io/badge/A11Y-96-green?style=for-the-badge "Accessibility") ![SEO](https://img.shields.io/badge/SEO-69-orange?style=for-the-badge "SEO") ![BEST PRACTICES](https://img.shields.io/badge/BEST%20PRACTICES-96-green?style=for-the-badge "Best Practices") | ![SI](https://img.shields.io/badge/SI-4.5s-orange?style=for-the-badge "Speed Index") ![FCP](https://img.shields.io/badge/FCP-0.8s-green?style=for-the-badge "First Contentful Paint") ![LCP](https://img.shields.io/badge/LCP-1.8s-green?style=for-the-badge "Largest Contentful Paint") ![TBT](https://img.shields.io/badge/TBT-0ms-green?style=for-the-badge "Total Blocking Time") ![CLS](https://img.shields.io/badge/CLS-0-green?style=for-the-badge "Cumulative Layout Shift") | [![PSI](https://www.gstatic.com/images/icons/material/product/2x/pagespeed_16dp.png)](https://developers.google.com/speed/pagespeed/insights/?url=https%3A%2F%2Flocalnav-arrow--milo--adobecom.aem.page%2F%3Fmartech%3Doff "Run again in Google PSI") |
| :desktop_computer: | [/?martech=off](https://localnav-arrow--milo--adobecom.aem.page/?martech=off) | [![PERFORMANCE](https://img.shields.io/badge/PERFORMANCE-99-green?style=for-the-badge "Performance")](https://googlechrome.github.io/lighthouse/scorecalc/#device=mobile&version=12.6.0&SI=1339.9342593183399&FCP=252&LCP=514.0504149999999&TBT=0&CLS=0 "See Calculator") ![A11Y](https://img.shields.io/badge/A11Y-96-green?style=for-the-badge "Accessibility") ![SEO](https://img.shields.io/badge/SEO-69-orange?style=for-the-badge "SEO") ![BEST PRACTICES](https://img.shields.io/badge/BEST%20PRACTICES-93-green?style=for-the-badge "Best Practices") | ![SI](https://img.shields.io/badge/SI-1.3s-orange?style=for-the-badge "Speed Index") ![FCP](https://img.shields.io/badge/FCP-0.3s-green?style=for-the-badge "First Contentful Paint") ![LCP](https://img.shields.io/badge/LCP-0.5s-green?style=for-the-badge "Largest Contentful Paint") ![TBT](https://img.shields.io/badge/TBT-0ms-green?style=for-the-badge "Total Blocking Time") ![CLS](https://img.shields.io/badge/CLS-0-green?style=for-the-badge "Cumulative Layout Shift") | [![PSI](https://www.gstatic.com/images/icons/material/product/2x/pagespeed_16dp.png)](https://developers.google.com/speed/pagespeed/insights/?url=https%3A%2F%2Flocalnav-arrow--milo--adobecom.aem.page%2F%3Fmartech%3Doff "Run again in Google PSI") |
| :iphone: | [/drafts/blaishram/test-urls/page?martech=off](https://localnav-arrow--milo--adobecom.aem.page/drafts/blaishram/test-urls/page?martech=off) | [![PERFORMANCE](https://img.shields.io/badge/PERFORMANCE-97-green?style=for-the-badge "Performance")](https://googlechrome.github.io/lighthouse/scorecalc/#device=mobile&version=12.6.0&SI=4494.628164264678&FCP=926&LCP=1671.85255&TBT=0&CLS=0.001964588755085348 "See Calculator") ![A11Y](https://img.shields.io/badge/A11Y-100-green?style=for-the-badge "Accessibility") ![SEO](https://img.shields.io/badge/SEO-69-orange?style=for-the-badge "SEO") ![BEST PRACTICES](https://img.shields.io/badge/BEST%20PRACTICES-93-green?style=for-the-badge "Best Practices") | ![SI](https://img.shields.io/badge/SI-4.5s-orange?style=for-the-badge "Speed Index") ![FCP](https://img.shields.io/badge/FCP-0.9s-green?style=for-the-badge "First Contentful Paint") ![LCP](https://img.shields.io/badge/LCP-1.7s-green?style=for-the-badge "Largest Contentful Paint") ![TBT](https://img.shields.io/badge/TBT-0ms-green?style=for-the-badge "Total Blocking Time") ![CLS](https://img.shields.io/badge/CLS-0.002-green?style=for-the-badge "Cumulative Layout Shift") | [![PSI](https://www.gstatic.com/images/icons/material/product/2x/pagespeed_16dp.png)](https://developers.google.com/speed/pagespeed/insights/?url=https%3A%2F%2Flocalnav-arrow--milo--adobecom.aem.page%2Fdrafts%2Fblaishram%2Ftest-urls%2Fpage%3Fmartech%3Doff "Run again in Google PSI") |
| :desktop_computer: | [/drafts/blaishram/test-urls/page?martech=off](https://localnav-arrow--milo--adobecom.aem.page/drafts/blaishram/test-urls/page?martech=off) | [![PERFORMANCE](https://img.shields.io/badge/PERFORMANCE-97-green?style=for-the-badge "Performance")](https://googlechrome.github.io/lighthouse/scorecalc/#device=mobile&version=12.6.0&SI=1771.08207767419&FCP=264&LCP=450.68417&TBT=0&CLS=0.0004023435996063968 "See Calculator") ![A11Y](https://img.shields.io/badge/A11Y-99-green?style=for-the-badge "Accessibility") ![SEO](https://img.shields.io/badge/SEO-61-orange?style=for-the-badge "SEO") ![BEST PRACTICES](https://img.shields.io/badge/BEST%20PRACTICES-96-green?style=for-the-badge "Best Practices") | ![SI](https://img.shields.io/badge/SI-1.8s-orange?style=for-the-badge "Speed Index") ![FCP](https://img.shields.io/badge/FCP-0.3s-green?style=for-the-badge "First Contentful Paint") ![LCP](https://img.shields.io/badge/LCP-0.5s-green?style=for-the-badge "Largest Contentful Paint") ![TBT](https://img.shields.io/badge/TBT-0ms-green?style=for-the-badge "Total Blocking Time") ![CLS](https://img.shields.io/badge/CLS-0-green?style=for-the-badge "Cumulative Layout Shift") | [![PSI](https://www.gstatic.com/images/icons/material/product/2x/pagespeed_16dp.png)](https://developers.google.com/speed/pagespeed/insights/?url=https%3A%2F%2Flocalnav-arrow--milo--adobecom.aem.page%2Fdrafts%2Fblaishram%2Ftest-urls%2Fpage%3Fmartech%3Doff "Run again in Google PSI") |
| :iphone: | [/drafts/blaishram/test-urls/page-gnav-footer-thin?martech=off](https://localnav-arrow--milo--adobecom.hlx.page/drafts/blaishram/test-urls/page-gnav-footer-thin?martech=off) | [![PERFORMANCE](https://img.shields.io/badge/PERFORMANCE-93-green?style=for-the-badge "Performance")](https://googlechrome.github.io/lighthouse/scorecalc/#device=mobile&version=12.6.0&SI=5837.898405538313&FCP=1379.9451800000002&LCP=2143.256245&TBT=0.5&CLS=0.0019038884489270369 "See Calculator") ![A11Y](https://img.shields.io/badge/A11Y-98-green?style=for-the-badge "Accessibility") ![SEO](https://img.shields.io/badge/SEO-69-orange?style=for-the-badge "SEO") ![BEST PRACTICES](https://img.shields.io/badge/BEST%20PRACTICES-96-green?style=for-the-badge "Best Practices") | ![SI](https://img.shields.io/badge/SI-5.8s-red?style=for-the-badge "Speed Index") ![FCP](https://img.shields.io/badge/FCP-1.4s-green?style=for-the-badge "First Contentful Paint") ![LCP](https://img.shields.io/badge/LCP-2.1s-green?style=for-the-badge "Largest Contentful Paint") ![TBT](https://img.shields.io/badge/TBT-0ms-green?style=for-the-badge "Total Blocking Time") ![CLS](https://img.shields.io/badge/CLS-0.002-green?style=for-the-badge "Cumulative Layout Shift") | [![PSI](https://www.gstatic.com/images/icons/material/product/2x/pagespeed_16dp.png)](https://developers.google.com/speed/pagespeed/insights/?url=https%3A%2F%2Flocalnav-arrow--milo--adobecom.hlx.page%2Fdrafts%2Fblaishram%2Ftest-urls%2Fpage-gnav-footer-thin%3Fmartech%3Doff "Run again in Google PSI") |
| :desktop_computer: | [/drafts/blaishram/test-urls/page-gnav-footer-thin?martech=off](https://localnav-arrow--milo--adobecom.hlx.page/drafts/blaishram/test-urls/page-gnav-footer-thin?martech=off) | [![PERFORMANCE](https://img.shields.io/badge/PERFORMANCE-98-green?style=for-the-badge "Performance")](https://googlechrome.github.io/lighthouse/scorecalc/#device=mobile&version=12.6.0&SI=1495.6518168697796&FCP=330.27648999999997&LCP=525.77649&TBT=8&CLS=0.0014040393614860236 "See Calculator") ![A11Y](https://img.shields.io/badge/A11Y-98-green?style=for-the-badge "Accessibility") ![SEO](https://img.shields.io/badge/SEO-69-orange?style=for-the-badge "SEO") ![BEST PRACTICES](https://img.shields.io/badge/BEST%20PRACTICES-96-green?style=for-the-badge "Best Practices") | ![SI](https://img.shields.io/badge/SI-1.5s-orange?style=for-the-badge "Speed Index") ![FCP](https://img.shields.io/badge/FCP-0.3s-green?style=for-the-badge "First Contentful Paint") ![LCP](https://img.shields.io/badge/LCP-0.5s-green?style=for-the-badge "Largest Contentful Paint") ![TBT](https://img.shields.io/badge/TBT-10ms-green?style=for-the-badge "Total Blocking Time") ![CLS](https://img.shields.io/badge/CLS-0.001-green?style=for-the-badge "Cumulative Layout Shift") | [![PSI](https://www.gstatic.com/images/icons/material/product/2x/pagespeed_16dp.png)](https://developers.google.com/speed/pagespeed/insights/?url=https%3A%2F%2Flocalnav-arrow--milo--adobecom.hlx.page%2Fdrafts%2Fblaishram%2Ftest-urls%2Fpage-gnav-footer-thin%3Fmartech%3Doff "Run again in Google PSI") |
| :iphone: | [/drafts/blaishram/test-urls/page-with-promo?martech=off](https://localnav-arrow--milo--adobecom.hlx.page/drafts/blaishram/test-urls/page-with-promo?martech=off) | [![PERFORMANCE](https://img.shields.io/badge/PERFORMANCE-94-green?style=for-the-badge "Performance")](https://googlechrome.github.io/lighthouse/scorecalc/#device=mobile&version=12.6.0&SI=5211.2220579918285&FCP=1434.8047000000001&LCP=2341.84846&TBT=0&CLS=0 "See Calculator") ![A11Y](https://img.shields.io/badge/A11Y-95-green?style=for-the-badge "Accessibility") ![SEO](https://img.shields.io/badge/SEO-61-orange?style=for-the-badge "SEO") ![BEST PRACTICES](https://img.shields.io/badge/BEST%20PRACTICES-96-green?style=for-the-badge "Best Practices") | ![SI](https://img.shields.io/badge/SI-5.2s-orange?style=for-the-badge "Speed Index") ![FCP](https://img.shields.io/badge/FCP-1.4s-green?style=for-the-badge "First Contentful Paint") ![LCP](https://img.shields.io/badge/LCP-2.3s-green?style=for-the-badge "Largest Contentful Paint") ![TBT](https://img.shields.io/badge/TBT-0ms-green?style=for-the-badge "Total Blocking Time") ![CLS](https://img.shields.io/badge/CLS-0-green?style=for-the-badge "Cumulative Layout Shift") | [![PSI](https://www.gstatic.com/images/icons/material/product/2x/pagespeed_16dp.png)](https://developers.google.com/speed/pagespeed/insights/?url=https%3A%2F%2Flocalnav-arrow--milo--adobecom.hlx.page%2Fdrafts%2Fblaishram%2Ftest-urls%2Fpage-with-promo%3Fmartech%3Doff "Run again in Google PSI") |
| :desktop_computer: | [/drafts/blaishram/test-urls/page-with-promo?martech=off](https://localnav-arrow--milo--adobecom.hlx.page/drafts/blaishram/test-urls/page-with-promo?martech=off) | [![PERFORMANCE](https://img.shields.io/badge/PERFORMANCE-97-green?style=for-the-badge "Performance")](https://googlechrome.github.io/lighthouse/scorecalc/#device=mobile&version=12.6.0&SI=1827.985323178448&FCP=346.97519000000005&LCP=534.5944700000001&TBT=0&CLS=0.000147320630469384 "See Calculator") ![A11Y](https://img.shields.io/badge/A11Y-99-green?style=for-the-badge "Accessibility") ![SEO](https://img.shields.io/badge/SEO-61-orange?style=for-the-badge "SEO") ![BEST PRACTICES](https://img.shields.io/badge/BEST%20PRACTICES-96-green?style=for-the-badge "Best Practices") | ![SI](https://img.shields.io/badge/SI-1.8s-orange?style=for-the-badge "Speed Index") ![FCP](https://img.shields.io/badge/FCP-0.3s-green?style=for-the-badge "First Contentful Paint") ![LCP](https://img.shields.io/badge/LCP-0.5s-green?style=for-the-badge "Largest Contentful Paint") ![TBT](https://img.shields.io/badge/TBT-0ms-green?style=for-the-badge "Total Blocking Time") ![CLS](https://img.shields.io/badge/CLS-0-green?style=for-the-badge "Cumulative Layout Shift") | [![PSI](https://www.gstatic.com/images/icons/material/product/2x/pagespeed_16dp.png)](https://developers.google.com/speed/pagespeed/insights/?url=https%3A%2F%2Flocalnav-arrow--milo--adobecom.hlx.page%2Fdrafts%2Fblaishram%2Ftest-urls%2Fpage-with-promo%3Fmartech%3Doff "Run again in Google PSI") |

author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-05-09T01:50:21Z
body: This PR is currently in the `needs-verification` state. Please assign a QA engineer to verify the changes.
author_association: CONTRIBUTOR
user: login: prativas22
created_at: 2025-05-09T04:31:10Z
body: When trying to use the arrow key to navigate while the LNAV was expanded, observed that it expanded the first dropdown item and then stopped navigating via the arrow key where multiple child items were there.
Details are added in the ticket for reference https://jira.corp.adobe.com/browse/MWPW-164678
author_association: NONE
user: login: github-actions[bot]
created_at: 2025-05-10T01:46:10Z
body: This pull request is not passing all required checks. Please see [this discussion](https://github.com/orgs/adobecom/discussions/997) for information on how to get all checks passing. Inconsistent checks can be manually retried. If a test absolutely can not pass for a good reason, please add a comment with an explanation to the PR.
author_association: CONTRIBUTOR
user: login: prativas22
created_at: 2025-05-16T13:29:11Z
body: Verified the the PR for arrow Up/Down key navigation for localnav; the result looks good
https://main--express-milo--adobecom.hlx.page/express/?milolibs=localnav-arrow
https://main--dc--adobecom.hlx.live/jp/acrobat?martech=off&milolibs=localnav-arrow
https://main--federal--adobecom.aem.page/drafts/blaishram/banner/branch-banner-sticky?martech=off&milolibs=localnav-arrow--milo--adobecom&newNav=true
https://main--cc--adobecom.hlx.live/ae_ar/creativecloud/business?milolibs=localnav-arrow
Recording
https://github.com/user-attachments/assets/4c59c5b3-284c-4b71-8b67-f59132f18202

Device
https://main--cc--adobecom.hlx.live/creativecloud/business?milolibs=localnav-arrow 
Recording
https://github.com/user-attachments/assets/609b440d-7f9b-46be-8c44-6b4b24237a0f


author_association: NONE