Skip to content

Commit 6f77582

Browse files
westonruterpierlon
andcommitted
Close Twenty Twenty and Twenty Twenty-One mobile menus when clicking on in-page anchor link menu items (#5720)
Co-authored-by: Pierre Gordon <[email protected]>
1 parent 21697e4 commit 6f77582

File tree

2 files changed

+41
-4
lines changed

2 files changed

+41
-4
lines changed

includes/sanitizers/class-amp-core-theme-sanitizer.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1885,6 +1885,9 @@ public function add_twentytwenty_modals() {
18851885
// the actionable elements in the modal. Therefore, the lightbox represents the "background".
18861886
$close_button_xpaths[] = "//*[ @id = '{$modal_id}' ]";
18871887

1888+
// Ensure anchor links also close the modal the same as the the Close Menu button.
1889+
$close_button_xpaths[] = sprintf( "//*[ @id = '{$modal_id}' ]//a[ @href and contains( @href, '#' ) ]" );
1890+
18881891
// Then, add the inner element of the lightbox as an open button xpath.
18891892
// This is done to prevent the above close action from closing the modal when an inner element is clicked.
18901893
// Workaround found here: https://stackoverflow.com/a/45971501 .
@@ -2159,6 +2162,21 @@ public function add_twentytwentyone_mobile_modal() {
21592162
AMP_DOM_Utils::add_amp_action( $menu_toggle, 'tap', "{$body_id}.toggleClass(class=primary-navigation-open)" );
21602163
AMP_DOM_Utils::add_amp_action( $menu_toggle, 'tap', "{$body_id}.toggleClass(class=lock-scrolling)" );
21612164
$menu_toggle->setAttribute( 'data-amp-bind-aria-expanded', "{$state_string} ? 'true' : 'false'" );
2165+
2166+
// Close the mobile modal when clicking in-page anchor links in the menu.
2167+
foreach ( $this->dom->xpath->query( '//*[ @id = "site-navigation" ]//a[ @href and contains( @href, "#" ) ]' ) as $link ) {
2168+
/** @var DOMElement $link */
2169+
AMP_DOM_Utils::add_amp_action( $link, 'tap', "AMP.setState({{$state_string}: false})" );
2170+
AMP_DOM_Utils::add_amp_action( $link, 'tap', "{$body_id}.toggleClass(class=primary-navigation-open,force=false)" );
2171+
AMP_DOM_Utils::add_amp_action( $link, 'tap', "{$body_id}.toggleClass(class=lock-scrolling,force=false)" );
2172+
2173+
// Ensure target is scrolled into view. Note that in-page anchor links currently do not work in the non-AMP
2174+
// version. Normally scrollTo shouldn't be necessary but it appears necessary due to scroll locking.
2175+
$target = preg_replace( '/.*#/', '', $link->getAttribute( 'href' ) );
2176+
if ( $target && $this->dom->getElementById( $target ) ) {
2177+
AMP_DOM_Utils::add_amp_action( $link, 'tap', "{$target}.scrollTo" );
2178+
}
2179+
}
21622180
}
21632181

21642182
/**

tests/php/test-class-amp-core-theme-sanitizer.php

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -514,7 +514,7 @@ public function test_amend_twentytwentyone_styles() {
514514
*/
515515
public function test_add_twentytwentyone_mobile_modal() {
516516
$html = '
517-
<nav>
517+
<nav id="site-navigation">
518518
<div class="menu-button-container">
519519
<button id="primary-mobile-menu">
520520
<span class="dropdown-icon open">Menu</span>
@@ -523,12 +523,14 @@ public function test_add_twentytwentyone_mobile_modal() {
523523
</div>
524524
<div class="primary-menu-container">
525525
<ul id="primary-menu-list">
526-
<li id="menu-item-1">Foo</li>
527-
<li id="menu-item-2">Bar</li>
528-
<li id="menu-item-3">Baz</li>
526+
<li id="menu-item-1"><a href="https://example.com/">Foo</a></li>
527+
<li id="menu-item-2"><a href="#colophon">Bar</a></li>
528+
<li id="menu-item-3"><a href="https://example.com/#site-footer">Baz</a></li>
529+
<li id="menu-item-2"><a href="' . esc_url( home_url( '/#colophon' ) ) . '">Quux</a></li>
529530
</ul>
530531
</div>
531532
</nav>
533+
<div id="colophon"></div>
532534
';
533535

534536
$dom = AMP_DOM_Utils::get_dom_from_content( $html );
@@ -539,6 +541,23 @@ public function test_add_twentytwentyone_mobile_modal() {
539541
$query = $dom->xpath->query( '//button[ @id = "primary-mobile-menu" and @data-amp-bind-aria-expanded and @on ]' );
540542

541543
$this->assertEquals( 1, $query->length );
544+
545+
$query = $dom->xpath->query( '//a[ @href ]' );
546+
$this->assertSame( 4, $query->length );
547+
foreach ( $query as $link ) {
548+
/** @var DOMElement $link */
549+
$href = $link->getAttribute( 'href' );
550+
if ( false !== strpos( $href, '#' ) ) {
551+
$this->assertTrue( $link->hasAttribute( 'on' ) );
552+
if ( false !== strpos( $href, '#colophon' ) ) {
553+
$this->assertStringContains( 'colophon.scrollTo', $link->getAttribute( 'on' ) );
554+
} else {
555+
$this->assertStringNotContains( 'colophon.scrollTo', $link->getAttribute( 'on' ) );
556+
}
557+
} else {
558+
$this->assertFalse( $link->hasAttribute( 'on' ) );
559+
}
560+
}
542561
}
543562

544563
/**

0 commit comments

Comments
 (0)