I’ll build this as a production-style mobile-menu.php template part for your RX theme: accessible menu, off-canvas drawer, search, dark mode hooks, social links, WooCommerce/account support, language area, schema-friendly markup, and safe WordPress escaping.
Below is a very advanced rx-theme/template-parts/header/mobile-menu.php file. It includes: mobile drawer, overlay, accessibility, search, menu fallback, secondary menu, account links, WooCommerce cart support, dark-mode button hook, language/currency hooks, social links, contact area, widget area, close buttons, no-JS fallback support, and safe escaping.
WordPress recommends wp_nav_menu() for theme menus, and get_search_form() can load your theme search form or the default search form. Escaping functions like esc_attr() help make output safer in attributes.
Create this file:
<?php
/**
* RX Theme Mobile Menu Template Part
*
* File: template-parts/header/mobile-menu.php
*
* @package RX_Theme
* @since 1.0.0
*/
defined( 'ABSPATH' ) || exit;
/**
* --------------------------------------------------------------------------
* Mobile Menu Settings
* --------------------------------------------------------------------------
*/
$rx_mobile_menu_id = 'rx-mobile-menu';
$rx_mobile_drawer_id = 'rx-mobile-drawer';
$rx_mobile_overlay_id = 'rx-mobile-overlay';
$rx_mobile_search_id = 'rx-mobile-search';
$rx_mobile_account_id = 'rx-mobile-account';
$rx_mobile_widget_area_id = 'mobile-menu-drawer';
$rx_site_name = get_bloginfo( 'name' );
$rx_site_description = get_bloginfo( 'description' );
$rx_home_url = home_url( '/' );
$rx_has_mobile_menu = has_nav_menu( 'mobile' );
$rx_has_primary_menu = has_nav_menu( 'primary' );
$rx_has_mobile_secondary_menu = has_nav_menu( 'mobile-secondary' );
$rx_has_footer_menu = has_nav_menu( 'footer' );
$rx_enable_search = apply_filters( 'rx_theme_mobile_menu_enable_search', true );
$rx_enable_account = apply_filters( 'rx_theme_mobile_menu_enable_account', true );
$rx_enable_cart = apply_filters( 'rx_theme_mobile_menu_enable_cart', true );
$rx_enable_social = apply_filters( 'rx_theme_mobile_menu_enable_social', true );
$rx_enable_contact = apply_filters( 'rx_theme_mobile_menu_enable_contact', true );
$rx_enable_dark_toggle = apply_filters( 'rx_theme_mobile_menu_enable_dark_toggle', true );
$rx_enable_language = apply_filters( 'rx_theme_mobile_menu_enable_language', true );
$rx_enable_widgets = apply_filters( 'rx_theme_mobile_menu_enable_widgets', true );
$rx_enable_quick_links = apply_filters( 'rx_theme_mobile_menu_enable_quick_links', true );
/**
* Social links from Customizer theme mods.
* You can create these theme mods later:
* rx_social_facebook, rx_social_x, rx_social_linkedin, rx_social_youtube,
* rx_social_instagram, rx_social_pinterest, rx_social_tiktok, rx_social_whatsapp.
*/
$rx_social_links = apply_filters(
'rx_theme_mobile_social_links',
array(
'facebook' => get_theme_mod( 'rx_social_facebook', '' ),
'x' => get_theme_mod( 'rx_social_x', '' ),
'linkedin' => get_theme_mod( 'rx_social_linkedin', '' ),
'youtube' => get_theme_mod( 'rx_social_youtube', '' ),
'instagram' => get_theme_mod( 'rx_social_instagram', '' ),
'pinterest' => get_theme_mod( 'rx_social_pinterest', '' ),
'tiktok' => get_theme_mod( 'rx_social_tiktok', '' ),
'whatsapp' => get_theme_mod( 'rx_social_whatsapp', '' ),
)
);
$rx_contact_email = apply_filters( 'rx_theme_mobile_contact_email', get_theme_mod( 'rx_contact_email', get_option( 'admin_email' ) ) );
$rx_contact_phone = apply_filters( 'rx_theme_mobile_contact_phone', get_theme_mod( 'rx_contact_phone', '' ) );
$rx_contact_text = apply_filters( 'rx_theme_mobile_contact_text', get_theme_mod( 'rx_contact_text', __( 'Need help? Contact us anytime.', 'rx-theme' ) ) );
$rx_quick_links = apply_filters(
'rx_theme_mobile_quick_links',
array(
array(
'label' => __( 'Home', 'rx-theme' ),
'url' => home_url( '/' ),
'icon' => 'home',
),
array(
'label' => __( 'Blog', 'rx-theme' ),
'url' => get_permalink( get_option( 'page_for_posts' ) ) ? get_permalink( get_option( 'page_for_posts' ) ) : home_url( '/' ),
'icon' => 'blog',
),
array(
'label' => __( 'Contact', 'rx-theme' ),
'url' => home_url( '/contact/' ),
'icon' => 'contact',
),
)
);
$rx_cart_count = 0;
$rx_cart_url = '';
if ( class_exists( 'WooCommerce' ) && function_exists( 'WC' ) && WC()->cart ) {
$rx_cart_count = WC()->cart->get_cart_contents_count();
$rx_cart_url = wc_get_cart_url();
}
$rx_account_url = is_user_logged_in() ? get_edit_profile_url( get_current_user_id() ) : wp_login_url( esc_url_raw( add_query_arg( array(), home_url( add_query_arg( null, null ) ) ) ) );
if ( class_exists( 'WooCommerce' ) && function_exists( 'wc_get_page_permalink' ) ) {
$rx_account_url = wc_get_page_permalink( 'myaccount' );
}
?>
<div
id="<?php echo esc_attr( $rx_mobile_menu_id ); ?>"
class="rx-mobile-menu"
data-rx-component="mobile-menu"
data-rx-open="false"
>
<button
type="button"
class="rx-mobile-menu__toggle"
aria-controls="<?php echo esc_attr( $rx_mobile_drawer_id ); ?>"
aria-expanded="false"
aria-label="<?php echo esc_attr__( 'Open mobile menu', 'rx-theme' ); ?>"
data-rx-mobile-open
>
<span class="rx-mobile-menu__toggle-icon" aria-hidden="true">
<span class="rx-mobile-menu__bar"></span>
<span class="rx-mobile-menu__bar"></span>
<span class="rx-mobile-menu__bar"></span>
</span>
<span class="rx-mobile-menu__toggle-text">
<?php esc_html_e( 'Menu', 'rx-theme' ); ?>
</span>
</button>
<div
id="<?php echo esc_attr( $rx_mobile_overlay_id ); ?>"
class="rx-mobile-menu__overlay"
hidden
data-rx-mobile-close
></div>
<aside
id="<?php echo esc_attr( $rx_mobile_drawer_id ); ?>"
class="rx-mobile-menu__drawer"
role="dialog"
aria-modal="true"
aria-labelledby="rx-mobile-menu-title"
aria-hidden="true"
tabindex="-1"
>
<div class="rx-mobile-menu__inner">
<header class="rx-mobile-menu__header">
<div class="rx-mobile-menu__brand">
<a class="rx-mobile-menu__logo-link" href="<?php echo esc_url( $rx_home_url ); ?>" rel="home">
<?php
if ( has_custom_logo() ) {
the_custom_logo();
} else {
?>
<span class="rx-mobile-menu__site-title">
<?php echo esc_html( $rx_site_name ); ?>
</span>
<?php if ( ! empty( $rx_site_description ) ) : ?>
<span class="rx-mobile-menu__site-description">
<?php echo esc_html( $rx_site_description ); ?>
</span>
<?php endif; ?>
<?php
}
?>
</a>
</div>
<button
type="button"
class="rx-mobile-menu__close"
aria-label="<?php echo esc_attr__( 'Close mobile menu', 'rx-theme' ); ?>"
data-rx-mobile-close
>
<span aria-hidden="true">×</span>
</button>
</header>
<div class="rx-mobile-menu__body">
<?php if ( $rx_enable_search ) : ?>
<section
id="<?php echo esc_attr( $rx_mobile_search_id ); ?>"
class="rx-mobile-menu__section rx-mobile-menu__search-section"
aria-label="<?php echo esc_attr__( 'Mobile search', 'rx-theme' ); ?>"
>
<h2 class="screen-reader-text">
<?php esc_html_e( 'Search this website', 'rx-theme' ); ?>
</h2>
<div class="rx-mobile-menu__search-wrap">
<?php
get_search_form(
array(
'aria_label' => __( 'Mobile search form', 'rx-theme' ),
)
);
?>
</div>
</section>
<?php endif; ?>
<?php if ( $rx_enable_quick_links && ! empty( $rx_quick_links ) ) : ?>
<section class="rx-mobile-menu__section rx-mobile-menu__quick-links-section">
<h2 class="rx-mobile-menu__section-title">
<?php esc_html_e( 'Quick Links', 'rx-theme' ); ?>
</h2>
<ul class="rx-mobile-menu__quick-links">
<?php foreach ( $rx_quick_links as $rx_quick_link ) : ?>
<?php
$rx_quick_label = isset( $rx_quick_link['label'] ) ? $rx_quick_link['label'] : '';
$rx_quick_url = isset( $rx_quick_link['url'] ) ? $rx_quick_link['url'] : '';
$rx_quick_icon = isset( $rx_quick_link['icon'] ) ? $rx_quick_link['icon'] : 'link';
if ( empty( $rx_quick_label ) || empty( $rx_quick_url ) ) {
continue;
}
?>
<li class="rx-mobile-menu__quick-link-item">
<a class="rx-mobile-menu__quick-link" href="<?php echo esc_url( $rx_quick_url ); ?>">
<span class="rx-mobile-menu__quick-link-icon rx-icon-<?php echo esc_attr( sanitize_html_class( $rx_quick_icon ) ); ?>" aria-hidden="true"></span>
<span class="rx-mobile-menu__quick-link-label">
<?php echo esc_html( $rx_quick_label ); ?>
</span>
</a>
</li>
<?php endforeach; ?>
</ul>
</section>
<?php endif; ?>
<nav
class="rx-mobile-menu__nav"
aria-label="<?php echo esc_attr__( 'Mobile primary navigation', 'rx-theme' ); ?>"
>
<h2 id="rx-mobile-menu-title" class="rx-mobile-menu__section-title">
<?php esc_html_e( 'Navigation', 'rx-theme' ); ?>
</h2>
<?php
if ( $rx_has_mobile_menu ) {
wp_nav_menu(
array(
'theme_location' => 'mobile',
'menu_id' => 'rx-mobile-primary-menu',
'menu_class' => 'rx-mobile-menu__list rx-mobile-menu__list--primary',
'container' => false,
'depth' => 4,
'fallback_cb' => false,
'link_before' => '<span class="rx-mobile-menu__link-text">',
'link_after' => '</span>',
'items_wrap' => '<ul id="%1$s" class="%2$s" role="list">%3$s</ul>',
)
);
} elseif ( $rx_has_primary_menu ) {
wp_nav_menu(
array(
'theme_location' => 'primary',
'menu_id' => 'rx-mobile-primary-menu',
'menu_class' => 'rx-mobile-menu__list rx-mobile-menu__list--primary',
'container' => false,
'depth' => 4,
'fallback_cb' => false,
'link_before' => '<span class="rx-mobile-menu__link-text">',
'link_after' => '</span>',
'items_wrap' => '<ul id="%1$s" class="%2$s" role="list">%3$s</ul>',
)
);
} else {
wp_page_menu(
array(
'menu_class' => 'rx-mobile-menu__page-list',
'show_home' => true,
'depth' => 3,
'before' => '<div class="rx-mobile-menu__fallback">',
'after' => '</div>',
'link_before' => '<span class="rx-mobile-menu__link-text">',
'link_after' => '</span>',
)
);
}
?>
</nav>
<?php if ( $rx_has_mobile_secondary_menu || $rx_has_footer_menu ) : ?>
<nav
class="rx-mobile-menu__nav rx-mobile-menu__nav--secondary"
aria-label="<?php echo esc_attr__( 'Mobile secondary navigation', 'rx-theme' ); ?>"
>
<h2 class="rx-mobile-menu__section-title">
<?php esc_html_e( 'More Pages', 'rx-theme' ); ?>
</h2>
<?php
if ( $rx_has_mobile_secondary_menu ) {
wp_nav_menu(
array(
'theme_location' => 'mobile-secondary',
'menu_id' => 'rx-mobile-secondary-menu',
'menu_class' => 'rx-mobile-menu__list rx-mobile-menu__list--secondary',
'container' => false,
'depth' => 2,
'fallback_cb' => false,
'link_before' => '<span class="rx-mobile-menu__link-text">',
'link_after' => '</span>',
'items_wrap' => '<ul id="%1$s" class="%2$s" role="list">%3$s</ul>',
)
);
} elseif ( $rx_has_footer_menu ) {
wp_nav_menu(
array(
'theme_location' => 'footer',
'menu_id' => 'rx-mobile-secondary-menu',
'menu_class' => 'rx-mobile-menu__list rx-mobile-menu__list--secondary',
'container' => false,
'depth' => 2,
'fallback_cb' => false,
'link_before' => '<span class="rx-mobile-menu__link-text">',
'link_after' => '</span>',
'items_wrap' => '<ul id="%1$s" class="%2$s" role="list">%3$s</ul>',
)
);
}
?>
</nav>
<?php endif; ?>
<?php if ( $rx_enable_account || $rx_enable_cart || $rx_enable_dark_toggle || $rx_enable_language ) : ?>
<section
id="<?php echo esc_attr( $rx_mobile_account_id ); ?>"
class="rx-mobile-menu__section rx-mobile-menu__actions-section"
>
<h2 class="rx-mobile-menu__section-title">
<?php esc_html_e( 'Tools', 'rx-theme' ); ?>
</h2>
<ul class="rx-mobile-menu__actions" role="list">
<?php if ( $rx_enable_account ) : ?>
<li class="rx-mobile-menu__action-item">
<a class="rx-mobile-menu__action-link rx-mobile-menu__action-link--account" href="<?php echo esc_url( $rx_account_url ); ?>">
<span class="rx-mobile-menu__action-icon rx-icon-user" aria-hidden="true"></span>
<span class="rx-mobile-menu__action-label">
<?php echo is_user_logged_in() ? esc_html__( 'My Account', 'rx-theme' ) : esc_html__( 'Login / Register', 'rx-theme' ); ?>
</span>
</a>
</li>
<?php endif; ?>
<?php if ( $rx_enable_cart && ! empty( $rx_cart_url ) ) : ?>
<li class="rx-mobile-menu__action-item">
<a class="rx-mobile-menu__action-link rx-mobile-menu__action-link--cart" href="<?php echo esc_url( $rx_cart_url ); ?>">
<span class="rx-mobile-menu__action-icon rx-icon-cart" aria-hidden="true"></span>
<span class="rx-mobile-menu__action-label">
<?php esc_html_e( 'Cart', 'rx-theme' ); ?>
</span>
<span class="rx-mobile-menu__cart-count">
<?php echo esc_html( number_format_i18n( absint( $rx_cart_count ) ) ); ?>
</span>
</a>
</li>
<?php endif; ?>
<?php if ( $rx_enable_dark_toggle ) : ?>
<li class="rx-mobile-menu__action-item">
<button
type="button"
class="rx-mobile-menu__action-button rx-mobile-menu__action-button--theme"
aria-pressed="false"
data-rx-theme-toggle
>
<span class="rx-mobile-menu__action-icon rx-icon-moon" aria-hidden="true"></span>
<span class="rx-mobile-menu__action-label">
<?php esc_html_e( 'Dark Mode', 'rx-theme' ); ?>
</span>
</button>
</li>
<?php endif; ?>
<?php if ( $rx_enable_language ) : ?>
<li class="rx-mobile-menu__action-item rx-mobile-menu__action-item--language">
<div class="rx-mobile-menu__language">
<?php
/**
* Hook for WPML, Polylang, TranslatePress, GTranslate, currency switcher, etc.
*
* Example:
* add_action( 'rx_theme_mobile_language_switcher', 'your_language_function' );
*/
do_action( 'rx_theme_mobile_language_switcher' );
?>
</div>
</li>
<?php endif; ?>
</ul>
</section>
<?php endif; ?>
<?php if ( $rx_enable_social && ! empty( array_filter( $rx_social_links ) ) ) : ?>
<section class="rx-mobile-menu__section rx-mobile-menu__social-section">
<h2 class="rx-mobile-menu__section-title">
<?php esc_html_e( 'Follow Us', 'rx-theme' ); ?>
</h2>
<ul class="rx-mobile-menu__social-list" role="list">
<?php foreach ( $rx_social_links as $rx_social_name => $rx_social_url ) : ?>
<?php
if ( empty( $rx_social_url ) ) {
continue;
}
$rx_social_label = ucfirst( str_replace( array( '-', '_' ), ' ', $rx_social_name ) );
?>
<li class="rx-mobile-menu__social-item">
<a
class="rx-mobile-menu__social-link rx-mobile-menu__social-link--<?php echo esc_attr( sanitize_html_class( $rx_social_name ) ); ?>"
href="<?php echo esc_url( $rx_social_url ); ?>"
target="_blank"
rel="noopener noreferrer nofollow"
aria-label="<?php echo esc_attr( sprintf( __( 'Follow %1$s on %2$s', 'rx-theme' ), $rx_site_name, $rx_social_label ) ); ?>"
>
<span class="rx-mobile-menu__social-icon rx-icon-<?php echo esc_attr( sanitize_html_class( $rx_social_name ) ); ?>" aria-hidden="true"></span>
<span class="rx-mobile-menu__social-text">
<?php echo esc_html( $rx_social_label ); ?>
</span>
</a>
</li>
<?php endforeach; ?>
</ul>
</section>
<?php endif; ?>
<?php if ( $rx_enable_contact && ( ! empty( $rx_contact_email ) || ! empty( $rx_contact_phone ) || ! empty( $rx_contact_text ) ) ) : ?>
<section class="rx-mobile-menu__section rx-mobile-menu__contact-section">
<h2 class="rx-mobile-menu__section-title">
<?php esc_html_e( 'Contact', 'rx-theme' ); ?>
</h2>
<?php if ( ! empty( $rx_contact_text ) ) : ?>
<p class="rx-mobile-menu__contact-text">
<?php echo esc_html( $rx_contact_text ); ?>
</p>
<?php endif; ?>
<ul class="rx-mobile-menu__contact-list" role="list">
<?php if ( ! empty( $rx_contact_email ) ) : ?>
<li class="rx-mobile-menu__contact-item">
<a class="rx-mobile-menu__contact-link" href="mailto:<?php echo esc_attr( antispambot( $rx_contact_email ) ); ?>">
<span class="rx-mobile-menu__contact-icon rx-icon-email" aria-hidden="true"></span>
<span><?php echo esc_html( antispambot( $rx_contact_email ) ); ?></span>
</a>
</li>
<?php endif; ?>
<?php if ( ! empty( $rx_contact_phone ) ) : ?>
<li class="rx-mobile-menu__contact-item">
<a class="rx-mobile-menu__contact-link" href="tel:<?php echo esc_attr( preg_replace( '/[^0-9+]/', '', $rx_contact_phone ) ); ?>">
<span class="rx-mobile-menu__contact-icon rx-icon-phone" aria-hidden="true"></span>
<span><?php echo esc_html( $rx_contact_phone ); ?></span>
</a>
</li>
<?php endif; ?>
</ul>
</section>
<?php endif; ?>
<?php if ( $rx_enable_widgets && is_active_sidebar( $rx_mobile_widget_area_id ) ) : ?>
<section class="rx-mobile-menu__section rx-mobile-menu__widgets-section">
<h2 class="rx-mobile-menu__section-title">
<?php esc_html_e( 'More', 'rx-theme' ); ?>
</h2>
<div class="rx-mobile-menu__widgets">
<?php dynamic_sidebar( $rx_mobile_widget_area_id ); ?>
</div>
</section>
<?php endif; ?>
</div>
<footer class="rx-mobile-menu__footer">
<p class="rx-mobile-menu__copyright">
© <?php echo esc_html( date_i18n( 'Y' ) ); ?>
<a href="<?php echo esc_url( $rx_home_url ); ?>">
<?php echo esc_html( $rx_site_name ); ?>
</a>
</p>
<button
type="button"
class="rx-mobile-menu__back-to-top"
data-rx-back-to-top
>
<?php esc_html_e( 'Back to Top', 'rx-theme' ); ?>
</button>
</footer>
</div>
</aside>
<noscript>
<style>
.rx-mobile-menu__drawer {
position: static;
visibility: visible;
opacity: 1;
transform: none;
height: auto;
max-height: none;
}
.rx-mobile-menu__toggle,
.rx-mobile-menu__close,
.rx-mobile-menu__overlay {
display: none;
}
</style>
</noscript>
</div>
<script>
/**
* RX Theme Mobile Menu Script
* You can move this later to assets/js/mobile-menu.js for better performance.
*/
(function () {
'use strict';
var root = document.getElementById('<?php echo esc_js( $rx_mobile_menu_id ); ?>');
if (!root) {
return;
}
var drawer = document.getElementById('<?php echo esc_js( $rx_mobile_drawer_id ); ?>');
var overlay = document.getElementById('<?php echo esc_js( $rx_mobile_overlay_id ); ?>');
var openButtons = root.querySelectorAll('[data-rx-mobile-open]');
var closeButtons = root.querySelectorAll('[data-rx-mobile-close]');
var themeToggle = root.querySelector('[data-rx-theme-toggle]');
var backToTop = root.querySelector('[data-rx-back-to-top]');
var focusableSelectors = [
'a[href]',
'button:not([disabled])',
'input:not([disabled])',
'select:not([disabled])',
'textarea:not([disabled])',
'[tabindex]:not([tabindex="-1"])'
].join(',');
var lastFocusedElement = null;
function getFocusableElements() {
if (!drawer) {
return [];
}
return Array.prototype.slice.call(drawer.querySelectorAll(focusableSelectors))
.filter(function (element) {
return !!(element.offsetWidth || element.offsetHeight || element.getClientRects().length);
});
}
function setExpandedState(isOpen) {
Array.prototype.forEach.call(openButtons, function (button) {
button.setAttribute('aria-expanded', isOpen ? 'true' : 'false');
});
root.setAttribute('data-rx-open', isOpen ? 'true' : 'false');
if (drawer) {
drawer.setAttribute('aria-hidden', isOpen ? 'false' : 'true');
}
if (overlay) {
if (isOpen) {
overlay.removeAttribute('hidden');
} else {
overlay.setAttribute('hidden', '');
}
}
document.documentElement.classList.toggle('rx-mobile-menu-is-open', isOpen);
document.body.classList.toggle('rx-mobile-menu-is-open', isOpen);
}
function openMenu() {
lastFocusedElement = document.activeElement;
setExpandedState(true);
window.setTimeout(function () {
var focusableElements = getFocusableElements();
if (focusableElements.length) {
focusableElements[0].focus();
} else if (drawer) {
drawer.focus();
}
}, 30);
}
function closeMenu() {
setExpandedState(false);
if (lastFocusedElement && typeof lastFocusedElement.focus === 'function') {
lastFocusedElement.focus();
}
}
function trapFocus(event) {
if (!root || root.getAttribute('data-rx-open') !== 'true') {
return;
}
if (event.key !== 'Tab') {
return;
}
var focusableElements = getFocusableElements();
if (!focusableElements.length) {
return;
}
var firstElement = focusableElements[0];
var lastElement = focusableElements[focusableElements.length - 1];
if (event.shiftKey && document.activeElement === firstElement) {
event.preventDefault();
lastElement.focus();
} else if (!event.shiftKey && document.activeElement === lastElement) {
event.preventDefault();
firstElement.focus();
}
}
function handleEscape(event) {
if (event.key === 'Escape' && root.getAttribute('data-rx-open') === 'true') {
closeMenu();
}
}
function setupSubmenus() {
var parents = root.querySelectorAll('.menu-item-has-children');
Array.prototype.forEach.call(parents, function (parent, index) {
var link = parent.querySelector(':scope > a');
var submenu = parent.querySelector(':scope > .sub-menu');
if (!link || !submenu) {
return;
}
var button = document.createElement('button');
var submenuId = submenu.getAttribute('id') || 'rx-mobile-submenu-' + index;
submenu.setAttribute('id', submenuId);
submenu.setAttribute('hidden', '');
button.type = 'button';
button.className = 'rx-mobile-menu__submenu-toggle';
button.setAttribute('aria-expanded', 'false');
button.setAttribute('aria-controls', submenuId);
button.innerHTML = '<span class="screen-reader-text"><?php echo esc_js( __( 'Toggle submenu', 'rx-theme' ) ); ?></span><span aria-hidden="true">+</span>';
link.insertAdjacentElement('afterend', button);
button.addEventListener('click', function () {
var expanded = button.getAttribute('aria-expanded') === 'true';
button.setAttribute('aria-expanded', expanded ? 'false' : 'true');
parent.classList.toggle('rx-submenu-is-open', !expanded);
if (expanded) {
submenu.setAttribute('hidden', '');
button.querySelector('[aria-hidden="true"]').textContent = '+';
} else {
submenu.removeAttribute('hidden');
button.querySelector('[aria-hidden="true"]').textContent = '−';
}
});
});
}
function setupThemeToggle() {
if (!themeToggle) {
return;
}
var storageKey = 'rx-theme-preference';
function applyTheme(theme) {
document.documentElement.setAttribute('data-rx-theme', theme);
themeToggle.setAttribute('aria-pressed', theme === 'dark' ? 'true' : 'false');
}
var savedTheme = window.localStorage ? localStorage.getItem(storageKey) : null;
if (savedTheme) {
applyTheme(savedTheme);
}
themeToggle.addEventListener('click', function () {
var currentTheme = document.documentElement.getAttribute('data-rx-theme') || 'light';
var nextTheme = currentTheme === 'dark' ? 'light' : 'dark';
applyTheme(nextTheme);
if (window.localStorage) {
localStorage.setItem(storageKey, nextTheme);
}
});
}
function setupBackToTop() {
if (!backToTop) {
return;
}
backToTop.addEventListener('click', function () {
window.scrollTo({
top: 0,
behavior: 'smooth'
});
closeMenu();
});
}
Array.prototype.forEach.call(openButtons, function (button) {
button.addEventListener('click', openMenu);
});
Array.prototype.forEach.call(closeButtons, function (button) {
button.addEventListener('click', closeMenu);
});
document.addEventListener('keydown', trapFocus);
document.addEventListener('keydown', handleEscape);
setupSubmenus();
setupThemeToggle();
setupBackToTop();
})();
</script>
Also add these menu locations in your inc/core/menus.php or functions.php:
register_nav_menus(
array(
'primary' => esc_html__( 'Primary Menu', 'rx-theme' ),
'mobile' => esc_html__( 'Mobile Menu', 'rx-theme' ),
'mobile-secondary' => esc_html__( 'Mobile Secondary Menu', 'rx-theme' ),
'footer' => esc_html__( 'Footer Menu', 'rx-theme' ),
)
);
And call it inside header.php:
<?php get_template_part( 'template-parts/header/mobile-menu' ); ?>
For best performance later, move the inline <script> into:
assets/js/mobile-menu.js
Then enqueue it from your enqueue.php.