Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 55 additions & 7 deletions python_docs_theme/layout.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,14 @@
{%- macro searchbox() %}
{# modified from sphinx/themes/basic/searchbox.html #}
{%- if builder != "htmlhelp" %}
<div class="inline-search" style="display: none" role="search">
<div class="inline-search" role="search">
<form class="inline-search" action="{{ pathto('search') }}" method="get">
<input placeholder="{{ _('Quick search') }}" type="text" name="q" />
<input placeholder="{{ _('Quick search') }}" aria-label="{{ _('Quick search') }}" type="text" name="q" />
<input type="submit" value="{{ _('Go') }}" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
<script type="text/javascript">$('.inline-search').show(0);</script>
{%- endif %}
{%- endmacro %}

Expand All @@ -35,12 +34,61 @@
{%- endif %}
{% endblock %}

{% block extrahead %}
{%- block extrahead -%}
<link rel="shortcut icon" type="image/png" href="{{ pathto('_static/' + theme_root_icon, 1) }}" />
{% if builder != "htmlhelp" %}
{% if not embedded %}<script type="text/javascript" src="{{ pathto('_static/copybutton.js', 1) }}"></script>{% endif %}
{% endif %}
{%- if builder != "htmlhelp" %}
{%- if not embedded %}
<script type="text/javascript" src="{{ pathto('_static/copybutton.js', 1) }}"></script>
<script type="text/javascript" src="{{ pathto('_static/menu.js', 1) }}"></script>
{%- endif -%}
{%- endif -%}
{{ super() }}
{%- endblock -%}

{%- block css -%}
<meta name="viewport" content="width=device-width, initial-scale=1.0">
Comment thread
obulat marked this conversation as resolved.
{{ super() }}
{%- endblock -%}

{%- block body_tag %}
{{ super() }}
<div class="mobile-nav">
<input type="checkbox" id="menuToggler" class="toggler__input"
aria-controls="navigation" aria-pressed="false" aria-expanded="false" />
<label for="menuToggler" class="toggler__label" role="button" aria-label="{{ _('Menu')}}">
<span></span>
</label>
<nav class="nav-content" role="navigation">
<img src="{{ pathto('_static/' + theme_root_icon, 1) }}" alt="Logo"/>
<div class="version_switcher_placeholder">{{ release }}</div>
{%- if pagename != "search" and builder != "singlehtml" %}
<div id="searchbox" role="search">
<form class="search" action="{{ pathto('search') }}" method="get">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"
class="search-icon">
<path fill-rule="nonzero"
d="M15.5 14h-.79l-.28-.27a6.5 6.5 0 001.48-5.34c-.47-2.78-2.79-5-5.59-5.34a6.505 6.505 0 00-7.27 7.27c.34 2.8 2.56 5.12 5.34 5.59a6.5 6.5 0 005.34-1.48l.27.28v.79l4.25 4.25c.41.41 1.08.41 1.49 0 .41-.41.41-1.08 0-1.49L15.5 14zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"></path>
</svg>
<input type="text" name="q" aria-label="{{ _('Quick search') }}"/>
<input type="submit" value="{{ _('Go') }}"/>
</form>
</div>
{%- endif %}
</nav>
<div class="menu-wrapper">
<nav class="menu" role="navigation" aria-label="main navigation">
<div class="language_switcher_placeholder"></div>
{%- if logo %}
<p class="logo"><a href="{{ pathto(master_doc)|e }}">
<img class="logo" src="{{ pathto('_static/' + logo, 1)|e }}" alt="Logo"/>
</a></p>
{%- endif %}
{%- for sidebartemplate in sidebars %}
{%- include sidebartemplate %}
{%- endfor %}
</nav>
</div>
</div>
{% endblock %}

{% block footer %}
Expand Down
55 changes: 55 additions & 0 deletions python_docs_theme/static/menu.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
document.addEventListener('DOMContentLoaded', function () {

// Make tables responsive by wrapping them in a div and making them scrollable
const tables = document.querySelectorAll('table.docutils');
tables.forEach(function(table){
table.outerHTML = '<div class="responsive-table__container">' + table.outerHTML + '</div>'
});

const togglerInput = document.querySelector('.toggler__input');
const togglerLabel = document.querySelector('.toggler__label');
const sideMenu = document.querySelector('.menu-wrapper');
const menuItems = document.querySelectorAll('.menu')
const doc = document.querySelector('.document');
const body = document.querySelector('body');

function closeMenu() {
togglerInput.checked = false;
sideMenu.setAttribute("aria-expanded", 'false');
sideMenu.setAttribute('aria-hidden', 'true');
togglerLabel.setAttribute('aria-pressed', 'false');
body.style.overflow = 'visible';
}
function openMenu() {
togglerInput.checked = true;
sideMenu.setAttribute("aria-expanded", 'true');
sideMenu.setAttribute('aria-hidden', 'false');
togglerLabel.setAttribute('aria-pressed', 'true');
body.style.overflow = 'hidden';
}

// Close menu when link on the sideMenu is clicked
sideMenu.addEventListener('click', function (event) {
let target = event.target;
if (target.tagName.toLowerCase() !== 'a') return;
closeMenu();
})
// Add accessibility data when sideMenu is opened/closed
togglerInput.addEventListener('change', function (e) {
togglerInput.checked ? openMenu() : closeMenu();
});
// Make sideMenu links tabbable only when visible
for(let menuItem of menuItems) {
if(togglerInput.checked) {
menuItem.setAttribute('tabindex', '0');
} else {
menuItem.setAttribute('tabindex', '-1');
}
}
// Close sideMenu when document body is clicked
doc.addEventListener('click', function () {
if (togglerInput.checked) {
closeMenu();
}
})
})
Comment on lines +2 to +55
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.

By moving the checkbox up in the dom tree it may be possible to implement this using only javascript and make it more accessible for people without javascript

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I replaced the checkbox with a button. Is this better for people without javascript?

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.

What I would have done is move the input as a checkbox directly next to the sidebar, reference it in the label via id and apply the styles based on whether the checkbox is checked or not. I may have time tomorrow to create a PR on your fork repo if you want to.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I have done it like this at first (checkbox input and applying styles based on :checked property). Then I was checking for accessibility and found this article which shows that a button as menu opener has some advantages regarding accessibility: namely, it is easier to set up keyboard handling. On the other hand, I just realized that people probably don't use keyboard for navigation on mobile, and it is more important to set up No-script solution than keyboard navigation on mobile.
Also, I looked at other documentation sites: readthedocs theme and VueJS docs, and their hamburger menu doesn't work without javascript.

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.

In addition if you follow this guide you also get a working css only solution with added accesibility using javascript

Loading