Skip to content

Hide the top menu on mobile - #3198

Open
hugovk wants to merge 1 commit into
python:mainfrom
hugovk:mobile-menu
Open

hugovk wants to merge 1 commit into
python:mainfrom
hugovk:mobile-menu

Conversation

@hugovk

@hugovk hugovk commented Oct 24, 2026

Copy link
Copy Markdown
Member

Description

When visiting https://www.python.org on mobile, the top menu takes up around half the screen:

This is quite annoying, and I don't remember ever clicked any of those links.

We could have it collapsed by default, but I think we could just remove it instead for mobile.

@hugovk
hugovk requested a review from JacobCoffee as a code owner October 24, 2026 16:02
Copilot AI balanced review requested due to automatic review settings October 24, 2026 16:02

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The template, scrolling handlers, and responsive styles are consistent, with no unresolved blocking issues.

No open issues 🎉

What changed in this PR

This PR reduces mobile header space by hiding the Python Network menu on small screens while preserving the skip-to-content link.

Changes:

  • Hide the top menu below 640px and remove adjacent borders.
  • Remove obsolete Python Network jump links, handlers, and styles.
  • Update footer links and smooth scrolling to target #top.
File Description
templates/​base.html Remove network jump links and retarget footer links.
static/​js/​script.js Remove obsolete handlers and update back-to-top scrolling.
static/​css/​style.css Remove unused jump-link styling.
static/​css/​mq.css Hide the mobile top menu and remove obsolete responsive styling.

Review effort: Balanced

@JacobCoffee

Copy link
Copy Markdown
Member

I am +100 for the idea, i was talking to guido about this earlier.. but this menu btn just jumps to the bottom and i hate it + i think itd be good to still go to the "big" sections like PSF
image

We can absolutely be more radical here, im not talking entire site redesign but as the core maintainer of the site i want the a11y for be.. accessible - and more generally useful.

if you want to take a stab at a better mobile nav that fits that criteria, i will merge it happily. once i (find?) have more time ill throw a model at it (am bad at frontend but know what works well/looks okay)

@JacobCoffee

Copy link
Copy Markdown
Member

ive come up with this on the plane
image

Details
diff --git a/static/css/mq.css b/static/css/mq.css
index 8e7cda84..42acf867 100644
--- a/static/css/mq.css
+++ b/static/css/mq.css
@@ -657,7 +657,51 @@ html[xmlns] .slides { display: block; }
   /* The header's dark top border is now the first pixel on the page,
      so drop it too */
   .main-header {
-    border-top: 0; } }
+    border-top: 0; }
+  /* With <dialog> support, script.js adds .has-mobile-nav and the Menu
+     button opens the drawer, which becomes the only menu: the options bar
+     shrinks to Menu + search (account and social links move into the drawer)
+     and the footer site map is dropped. Without it, everything stays as is. */
+  .has-mobile-nav #site-map-link,
+  .has-mobile-nav .options-bar .breaker,
+  .has-mobile-nav .options-bar .adjust-font-size,
+  .has-mobile-nav .options-bar .winkwink-nudgenudge,
+  .has-mobile-nav .options-bar [data-html-include],
+  .has-mobile-nav .main-footer-links {
+    display: none; }
+  .has-mobile-nav .options-bar {
+    display: flex;
+    align-items: stretch; }
+  .has-mobile-nav .mobile-nav-toggle {
+    display: block;
+    flex: none; }
+  .has-mobile-nav .search-the-site {
+    display: block;
+    flex: 1 1 auto;
+    min-width: 0;
+    padding: 0 0.5em 0 0;
+    border-right: 0; }
+    .has-mobile-nav .search-the-site fieldset {
+      display: flex;
+      align-items: center;
+      min-width: 0;
+      height: 100%;
+      margin: 0;
+      padding: 0;
+      border: 0; }
+    .has-mobile-nav .search-the-site .icon-search {
+      flex: none; }
+  .has-mobile-nav .search-field,
+  .has-mobile-nav .search-field:focus {
+    flex: 1 1 auto;
+    width: auto;
+    min-width: 0;
+    min-height: 2.25em;
+    margin: 0.3125em 0;
+    padding: 0 0.5em; }
+  .has-mobile-nav .search-button {
+    flex: none;
+    margin: 0 0 0 0.375em; } }
 /* - - - Larger than 640px - - - */
 @media (min-width: 40em) {
   body:after {
diff --git a/static/css/style.css b/static/css/style.css
index d3daedaf..f2ded874 100644
--- a/static/css/style.css
+++ b/static/css/style.css
@@ -3913,3 +3913,261 @@ span.highlighted {
   font-size: 75%; }
 #update-sponsorship-assets .form-actions {
   margin: 0.5em 0; }
+
+/* ! ===== Mobile navigation ===== */
+/* A modal drawer for small screens, opened by .mobile-nav-toggle in the options bar.
+ * The toggle is only shown below 640px when the browser supports <dialog> (see mq.css);
+ * everywhere else the original #site-map-link remains. */
+.mobile-nav-toggle,
+.mobile-nav-close,
+.mobile-nav-expand {
+  /* Undo the global button styling */
+  margin: 0;
+  padding: 0;
+  border: 0;
+  border-radius: 0;
+  background: none;
+  box-shadow: none;
+  text-shadow: none;
+  color: inherit !important;
+  font: inherit;
+  line-height: 1;
+  text-align: center;
+  white-space: nowrap;
+  cursor: pointer;
+  -webkit-tap-highlight-color: transparent; }
+
+.mobile-nav-toggle {
+  display: none;
+  vertical-align: middle;
+  min-height: 2.875em;
+  padding: 0 1.125em;
+  border-right: 1px solid #070a0c;
+  color: #bbbbbb !important; }
+  .mobile-nav-toggle svg {
+    display: inline-block;
+    vertical-align: -0.1875em;
+    margin-right: 0.4375em; }
+  .mobile-nav-toggle:hover, .mobile-nav-toggle:focus, .mobile-nav-toggle:active {
+    color: white !important;
+    background: none; }
+
+.mobile-nav-toggle:focus-visible,
+.mobile-nav a:focus-visible,
+.mobile-nav button:focus-visible {
+  outline: 2px solid #ffd343;
+  outline-offset: -2px; }
+
+.mobile-nav {
+  /* Turn the centred UA dialog box into a full-height drawer on the right */
+  position: fixed;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: auto;
+  width: 22em;
+  max-width: calc(100% - 3.5em);
+  height: 100%;
+  max-height: 100%;
+  margin: 0;
+  padding: 0;
+  border: 0;
+  overflow-y: auto;
+  overscroll-behavior: contain;
+  -webkit-overflow-scrolling: touch;
+  color: #c4ccd4;
+  background-color: #1e2933;
+  box-shadow: -0.5em 0 2em rgba(0, 0, 0, 0.45); }
+  .mobile-nav::backdrop {
+    background-color: rgba(8, 12, 16, 0.6); }
+  .mobile-nav[open] {
+    animation: mobile-nav-in 320ms cubic-bezier(0.16, 1, 0.3, 1); }
+  .mobile-nav[open]::backdrop {
+    animation: mobile-nav-fade 320ms ease-out; }
+
+@keyframes mobile-nav-in {
+  from { transform: translateX(100%); }
+  to { transform: none; } }
+
+@keyframes mobile-nav-fade {
+  from { opacity: 0; }
+  to { opacity: 1; } }
+
+@media (prefers-reduced-motion: reduce) {
+  .mobile-nav[open],
+  .mobile-nav[open]::backdrop,
+  .mobile-nav-expand svg {
+    animation: none;
+    transition: none; } }
+
+/* Lock the page behind the open drawer */
+html.mobile-nav-open,
+html.mobile-nav-open body {
+  overflow: hidden; }
+
+.mobile-nav-panel {
+  min-height: 100%;
+  padding-bottom: 2em; }
+
+.mobile-nav-header {
+  position: sticky;
+  top: 0;
+  z-index: 1;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  padding: 0.5em 0.5em 0.5em 1.25em;
+  background-color: #1e2933;
+  border-bottom: 1px solid #070a0c;
+  box-shadow: 0 1px 0 #2d3e4d; }
+
+.mobile-nav-title {
+  margin: 0;
+  color: white;
+  font-family: SourceSansProBold, Arial, sans-serif;
+  font-size: 1.25em;
+  line-height: 1.2; }
+
+.mobile-nav-close {
+  display: inline-flex;
+  align-items: center;
+  min-height: 2.75em;
+  padding: 0 0.875em;
+  border-radius: 6px;
+  color: #c4ccd4 !important; }
+  .mobile-nav-close svg {
+    margin-right: 0.5em; }
+  .mobile-nav-close:focus {
+    /* Beat the global button:focus gradient; the focus ring comes from :focus-visible */
+    color: #c4ccd4 !important;
+    background: none; }
+  .mobile-nav-close:hover, .mobile-nav-close:active {
+    color: white !important;
+    background: #2d3e4d; }
+
+.mobile-nav-heading {
+  margin: 1.5em 1.25em 0.625em;
+  color: #9fb3c8;
+  font-family: SourceSansProBold, Arial, sans-serif;
+  font-size: 1em;
+  line-height: 1.25; }
+
+/* Python Network: the six sister sites, keeping their colour stripes from the desktop top bar */
+.mobile-nav-network-list {
+  display: grid;
+  /* Three across on most phones, two on the narrowest */
+  grid-template-columns: repeat(auto-fit, minmax(5.5em, 1fr));
+  gap: 0.5em;
+  margin: 0 1.25em; }
+  .mobile-nav-network-list li {
+    border-top: 3px solid #3776ab;
+    border-radius: 0 0 6px 6px;
+    background-color: #253441; }
+  .mobile-nav-network-list .psf-meta { border-top-color: #78797a; }
+  .mobile-nav-network-list .docs-meta { border-top-color: #ffd343; }
+  .mobile-nav-network-list .pypi-meta { border-top-color: #82b043; }
+  .mobile-nav-network-list .jobs-meta { border-top-color: #a06ba7; }
+  .mobile-nav-network-list .shop-meta { border-top-color: #b55863; }
+  .mobile-nav-network-list a {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    min-height: 2.75em;
+    padding: 0.25em 0.375em;
+    color: #c4ccd4;
+    line-height: 1.2;
+    text-align: center;
+    border-radius: inherit; }
+    .mobile-nav-network-list a:hover, .mobile-nav-network-list a:focus {
+      color: white;
+      background-color: #2d3e4d; }
+  .mobile-nav-network-list a[aria-current] {
+    color: white;
+    font-family: SourceSansProBold, Arial, sans-serif;
+    background-color: #13191e; }
+
+/* Sections of the current site, built from #mainnav */
+.mobile-nav-section-list {
+  margin: 0;
+  border-top: 1px solid #2d3e4d; }
+
+.mobile-nav-section {
+  border-bottom: 1px solid #2d3e4d; }
+
+.mobile-nav-row {
+  display: flex;
+  align-items: stretch; }
+  .mobile-nav-row a {
+    flex: 1 1 auto;
+    display: flex;
+    align-items: center;
+    min-height: 3em;
+    padding: 0.375em 1.25em;
+    color: #f0f0f0;
+    font-size: 1.125em;
+    line-height: 1.25; }
+
+.mobile-nav-expand {
+  flex: 0 0 3.25em;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  border-left: 1px solid #2d3e4d;
+  color: #9fb3c8 !important; }
+  .mobile-nav-expand svg {
+    transition: transform 200ms cubic-bezier(0.16, 1, 0.3, 1); }
+  .mobile-nav-expand[aria-expanded="true"] svg {
+    transform: rotate(180deg); }
+  .mobile-nav-expand:focus {
+    color: #9fb3c8 !important;
+    background: none; }
+  .mobile-nav-expand:hover, .mobile-nav-expand:active {
+    color: white !important;
+    background: #2d3e4d; }
+
+.mobile-nav-subnav {
+  margin: 0;
+  padding: 0.25em 0 0.625em;
+  background-color: #18222b; }
+  .mobile-nav-subnav a {
+    display: flex;
+    align-items: center;
+    min-height: 2.75em;
+    padding: 0.25em 1.25em 0.25em 2em;
+    color: #c4ccd4;
+    line-height: 1.25; }
+
+.mobile-nav-row a:hover, .mobile-nav-row a:focus,
+.mobile-nav-subnav a:hover, .mobile-nav-subnav a:focus {
+  color: white;
+  background-color: #253441; }
+
+.mobile-nav-section-list a[aria-current="page"] {
+  color: white;
+  font-family: SourceSansProBold, Arial, sans-serif;
+  text-decoration: underline;
+  text-decoration-color: #ffd343;
+  text-decoration-thickness: 2px;
+  text-underline-offset: 0.3em; }
+
+/* Account and social links: flat lists below the sections */
+.mobile-nav-account ul,
+.mobile-nav-social-list {
+  margin: 0;
+  border-top: 1px solid #2d3e4d; }
+  .mobile-nav-account li,
+  .mobile-nav-social-list li {
+    border-bottom: 1px solid #2d3e4d; }
+  .mobile-nav-account a,
+  .mobile-nav-social-list a {
+    display: flex;
+    align-items: center;
+    min-height: 3em;
+    padding: 0.375em 1.25em;
+    color: #f0f0f0;
+    font-size: 1.125em;
+    line-height: 1.25; }
+    .mobile-nav-account a:hover, .mobile-nav-account a:focus,
+    .mobile-nav-social-list a:hover, .mobile-nav-social-list a:focus {
+      color: white;
+      background-color: #253441; }
diff --git a/static/js/script.js b/static/js/script.js
index ce7a6cbf..d364f422 100644
--- a/static/js/script.js
+++ b/static/js/script.js
@@ -376,3 +376,202 @@ $().ready(function() {
 
     getPythonStatus();
 });
+
+
+/*
+ * Small-screen navigation drawer (#mobile-nav).
+ * Without <dialog> support the Menu link keeps jumping to the footer site map.
+ */
+(function () {
+    var dialog = document.getElementById('mobile-nav');
+    var toggle = document.getElementById('mobile-nav-toggle');
+    if (!dialog || !toggle || typeof dialog.showModal !== 'function') {
+        return;
+    }
+
+    var root = document.documentElement;
+    var sectionList = dialog.querySelector('.mobile-nav-sections .mobile-nav-section-list');
+    var accountNav = dialog.querySelector('.mobile-nav-account');
+    var chevron = '<svg aria-hidden="true" focusable="false" width="16" height="16" viewBox="0 0 16 16">' +
+        '<path d="M3.5 6l4.5 4.5L12.5 6" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>';
+    var built = false;
+
+    root.classList.add('has-mobile-nav');
+
+    function normalizedPath(link) {
+        return link.host === window.location.host ? link.pathname.replace(/\/+$/, '') : null;
+    }
+
+    function makeLink(source) {
+        var link = document.createElement('a');
+        link.href = source.getAttribute('href');
+        link.textContent = source.textContent.trim();
+        return link;
+    }
+
+    function setExpanded(button, expanded) {
+        button.setAttribute('aria-expanded', expanded ? 'true' : 'false');
+        document.getElementById(button.getAttribute('aria-controls')).hidden = !expanded;
+    }
+
+    /* Highlight the sister site we are on, matching the body class used by the desktop top bar. */
+    function markCurrentNetwork() {
+        var bodyClasses = document.body.className.split(/\s+/);
+        var items = dialog.querySelectorAll('.mobile-nav-network-list li');
+        for (var i = 0; i < items.length; i++) {
+            if (bodyClasses.indexOf(items[i].getAttribute('data-network')) !== -1) {
+                var link = items[i].querySelector('a');
+                link.setAttribute('aria-current', 'true');
+                return link.getAttribute('data-hint') || link.textContent.trim();
+            }
+        }
+        return null;
+    }
+
+    /* Copy links into a flat list, skipping duplicate destinations. */
+    function fillLinkList(list, sources) {
+        var seen = {};
+        list.innerHTML = '';
+        for (var i = 0; i < sources.length; i++) {
+            var link = makeLink(sources[i]);
+            if (seen[link.href]) {
+                continue;
+            }
+            seen[link.href] = true;
+            var item = document.createElement('li');
+            item.appendChild(link);
+            list.appendChild(item);
+        }
+        return list.children.length;
+    }
+
+    /* The account menu is loaded into the options bar asynchronously (html-includes.js), so refresh it on every open. */
+    function buildAccount() {
+        var links = document.querySelectorAll('.options-bar .account-signin a');
+        accountNav.hidden = !fillLinkList(accountNav.querySelector('ul'), links);
+    }
+
+    /* Mirror this page's #mainnav (it differs between Python, PSF, Jobs, ...) as disclosure groups. */
+    function build() {
+        var currentSite = markCurrentNetwork();
+        var tiers = document.querySelectorAll('#mainnav .tier-1');
+        var here = window.location.pathname.replace(/\/+$/, '');
+        var currentMarked = false;
+
+        if (currentSite) {
+            document.getElementById('mobile-nav-sections-title').textContent = currentSite;
+        }
+
+        for (var i = 0; i < tiers.length; i++) {
+            var source = tiers[i].querySelector('a');
+            if (!source) {
+                continue;
+            }
+            var item = document.createElement('li');
+            var row = document.createElement('div');
+            var link = makeLink(source);
+            item.className = 'mobile-nav-section';
+            row.className = 'mobile-nav-row';
+            row.appendChild(link);
+            item.appendChild(row);
+            sectionList.appendChild(item);
+
+            /* Skip desktop "supernav" panels in case they were loaded at a wider width. */
+            var children = tiers[i].querySelectorAll('.subnav > .tier-2:not(.super-navigation) > a');
+            var groupLinks = [link];
+            var button = null;
+            if (children.length) {
+                var groupId = 'mobile-nav-group-' + (i + 1);
+                var subnav = document.createElement('ul');
+                var label = document.createElement('span');
+                button = document.createElement('button');
+                subnav.className = 'mobile-nav-subnav';
+                subnav.id = groupId;
+                for (var j = 0; j < children.length; j++) {
+                    var child = document.createElement('li');
+                    var childLink = makeLink(children[j]);
+                    child.appendChild(childLink);
+                    subnav.appendChild(child);
+                    groupLinks.push(childLink);
+                }
+                button.type = 'button';
+                button.className = 'mobile-nav-expand';
+                button.setAttribute('aria-controls', groupId);
+                button.innerHTML = chevron;
+                label.className = 'screen-reader-text';
+                label.textContent = 'More ' + link.textContent + ' pages';
+                button.insertBefore(label, button.firstChild);
+                row.appendChild(button);
+                item.appendChild(subnav);
+                setExpanded(button, /\bselected\b/.test(source.className));
+            }
+
+            /* Mark the first link to this page and open its group. */
+            for (var k = 0; k < groupLinks.length && !currentMarked; k++) {
+                if (normalizedPath(groupLinks[k]) === here) {
+                    groupLinks[k].setAttribute('aria-current', 'page');
+                    currentMarked = true;
+                    if (button) {
+                        setExpanded(button, true);
+                    }
+                }
+            }
+        }
+
+        if (!sectionList.children.length) {
+            dialog.querySelector('.mobile-nav-sections').hidden = true;
+        }
+        if (!fillLinkList(dialog.querySelector('.mobile-nav-social-list'),
+                          document.querySelectorAll('.options-bar .winkwink-nudgenudge .subnav a'))) {
+            dialog.querySelector('.mobile-nav-social').hidden = true;
+        }
+        built = true;
+    }
+
+    toggle.addEventListener('click', function () {
+        if (!built) {
+            build();
+        }
+        buildAccount();
+        dialog.showModal();
+        root.classList.add('mobile-nav-open');
+    });
+
+    dialog.addEventListener('close', function () {
+        root.classList.remove('mobile-nav-open');
+        toggle.focus();
+    });
+
+    dialog.addEventListener('click', function (event) {
+        var target = event.target;
+        /* A click on the backdrop targets the dialog itself, outside its box. */
+        if (target === dialog) {
+            var box = dialog.getBoundingClientRect();
+            if (event.clientX < box.left || event.clientX > box.right ||
+                event.clientY < box.top || event.clientY > box.bottom) {
+                dialog.close();
+            }
+            return;
+        }
+        var expand = target.closest('.mobile-nav-expand');
+        if (expand) {
+            setExpanded(expand, expand.getAttribute('aria-expanded') !== 'true');
+        } else if (target.closest('[data-mobile-nav-close]')) {
+            dialog.close();
+        }
+    });
+
+    /* The drawer is for small screens only; rotating or resizing past 640px closes it. */
+    window.matchMedia('(min-width: 40em)').addEventListener('change', function (event) {
+        if (event.matches && dialog.open) {
+            dialog.close();
+        }
+    });
+
+    /* Don't come back to an open drawer via the back/forward cache. */
+    window.addEventListener('pageshow', function (event) {
+        if (event.persisted && dialog.open) {
+            dialog.close();
+        }
+    });
+})();
diff --git a/templates/base.html b/templates/base.html
index 20d94ff4..69353fbc 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -154,7 +154,7 @@
                     <a href="https://donate.python.org/" class="donate-button">Donate</a>
                     <div class="options-bar">
                         {# Its a little ugly, but no space between elements makes the inline-block style work better #}
-                        <a id="site-map-link" class="jump-to-menu" href="#site-map"><span class="menu-icon">&equiv;</span> Menu</a><form class="search-the-site" action="/search/" method="get">
+                        <a id="site-map-link" class="jump-to-menu" href="#site-map"><span class="menu-icon">&equiv;</span> Menu</a><button type="button" id="mobile-nav-toggle" class="mobile-nav-toggle" aria-haspopup="dialog" aria-controls="mobile-nav"><svg aria-hidden="true" focusable="false" width="18" height="18" viewBox="0 0 18 18"><path d="M2 4h14M2 9h14M2 14h14" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>Menu</button><form class="search-the-site" action="/search/" method="get">
                             <fieldset title="Search Python.org">
 
                                 <span aria-hidden="true" class="icon-search"></span>
@@ -291,6 +291,32 @@
 
     </div><!-- end #touchnav-wrapper -->
 
+    {# Small-screen navigation, opened by #mobile-nav-toggle. script.js fills the lists from #mainnav and the options bar (account, social) so per-section navigation blocks carry over. #}
+    <dialog id="mobile-nav" class="mobile-nav do-not-print" aria-labelledby="mobile-nav-title">
+        <div class="mobile-nav-panel">
+            <div class="mobile-nav-header">
+                <h2 id="mobile-nav-title" class="mobile-nav-title">Menu</h2>
+                <button type="button" class="mobile-nav-close" data-mobile-nav-close><svg aria-hidden="true" focusable="false" width="16" height="16" viewBox="0 0 16 16"><path d="M3 3l10 10M13 3L3 13" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>Close</button>
+            </div>
+            <nav class="mobile-nav-network" aria-labelledby="mobile-nav-network-title">
+                <h3 id="mobile-nav-network-title" class="mobile-nav-heading">Python Network</h3>
+                {% sitetree_menu from "main" include "trunk" template "sitetree/mobile_network.html" %}
+            </nav>
+            <nav class="mobile-nav-sections" aria-labelledby="mobile-nav-sections-title">
+                <h3 id="mobile-nav-sections-title" class="mobile-nav-heading">Sections</h3>
+                <ul class="mobile-nav-section-list"></ul>
+            </nav>
+            <nav class="mobile-nav-account" aria-labelledby="mobile-nav-account-title" hidden>
+                <h3 id="mobile-nav-account-title" class="mobile-nav-heading">Account</h3>
+                <ul class="mobile-nav-section-list"></ul>
+            </nav>
+            <nav class="mobile-nav-social" aria-labelledby="mobile-nav-social-title">
+                <h3 id="mobile-nav-social-title" class="mobile-nav-heading">Socialize</h3>
+                <ul class="mobile-nav-social-list"></ul>
+            </nav>
+        </div>
+    </dialog>
+
     {% block javascript %}
     <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
     <script nonce="{{ request.csp_nonce }}">window.jQuery || document.write('<script src="{{ STATIC_URL }}js/libs/jquery-1.8.2.min.js"><\/script>')</script>
diff --git a/templates/sitetree/mobile_network.html b/templates/sitetree/mobile_network.html
new file mode 100644
index 00000000..d971f0d4
--- /dev/null
+++ b/templates/sitetree/mobile_network.html
@@ -0,0 +1,8 @@
+{% load sitetree %}
+<ul class="mobile-nav-network-list">
+    {% for item in sitetree_items %}
+    <li class="{{ item.alias }}" data-network="{{ item.alias|cut:'-meta' }}">
+        <a href="{% sitetree_url for item %}"{% if item.hint %} data-hint="{{ item.hint }}"{% endif %}>{{ item.title_resolved }}</a>
+    </li>
+    {% endfor %}
+</ul>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants