Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make the theme responsive #46

Merged
merged 24 commits into from
May 7, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
64 changes: 62 additions & 2 deletions python_docs_theme/layout.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
<input type="hidden" name="area" value="default" />
</form>
</div>
<script type="text/javascript">$('.inline-search').show(0);</script>
<script type="text/javascript">document.querySelector('.inline-search').style.display = 'block';</script>
{%- endif %}
{%- endmacro %}

Expand All @@ -38,11 +38,71 @@
{% 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 %}
{% 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">
obulat marked this conversation as resolved.
Show resolved Hide resolved
{{ super() }}
{%- endblock %}

{%- block body_tag %}
<body>
<nav class="mobile-nav">
<input type="checkbox" class="toggler">
<div class="hamburger">
<div></div>
</div>
<div class="nav-content">
<img src="{{ pathto('_static/' + theme_root_icon, 1) }}" alt="Logo"/>
{%- if switchers is defined %}
<div class="version_switcher_placeholder">{{ release }}</div>
{% endif -%}
{%- if pagename != "search" and builder != "singlehtml" %}
<div id="searchbox" style="display: none" role="search">
<form class="search" action="{{ pathto('search') }}" method="get">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden="true"
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>
<label id="mobilesearchlabel" for="searchbox">{{ _('Quick search') }}</label>
<input type="text" name="q" aria-labelledby="searchlabel"/>
obulat marked this conversation as resolved.
Show resolved Hide resolved
<input type="submit" value="{{ _('Go') }}"/>
</form>
</div>
<script>document.getElementById('searchbox').style.display='block';</script>
obulat marked this conversation as resolved.
Show resolved Hide resolved
{%- endif %}
</div>
</nav>
{% endblock %}

{% block sidebar1 %}
<div class="menu-wrapper">
<nav class="menu" role="navigation" aria-label="main navigation">
{%- if switchers is defined %}
<div class="language_switcher_placeholder">{{ language or 'en' }}</div>
{% endif -%}
{%- block sidebarlogo %}
{%- 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 %}
{%- endblock %}
{#- new style sidebar: explicitly include/exclude templates #}
{%- for sidebartemplate in sidebars %}
{%- include sidebartemplate %}
{%- endfor %}
</nav>
</div>
{% endblock %}

{% block footer %}
<div class="footer">
&copy; <a href="{{ pathto('copyright') }}">{% trans %}Copyright{% endtrans %}</a> {{ copyright|e }}.
Expand Down
22 changes: 22 additions & 0 deletions python_docs_theme/static/menu.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@

document.addEventListener('DOMContentLoaded', function () {
const toggler = document.querySelector('.toggler');
const sideMenu = document.querySelector('.menu-wrapper');
const doc = document.querySelector('.document');
function closeMenu() {
sideMenu.classList.remove('open');
toggler.checked = false;
}
toggler.addEventListener('change', function (e) {
if (toggler.checked) {
sideMenu.classList.add('open');
} else {
closeMenu();
}
});
doc.addEventListener('click', function () {
if (toggler.checked) {
closeMenu();
}
})
})
Copy link
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
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
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
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
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

236 changes: 235 additions & 1 deletion python_docs_theme/static/pydoctheme.css
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
@import url("default.css");

* {
box-sizing: border-box;
}
obulat marked this conversation as resolved.
Show resolved Hide resolved

body {
background-color: white;
margin-left: 1em;
margin-right: 1em;
}

.mobile-nav,
.menu-wrapper {
display: none;
}

div.related {
margin-bottom: 1.2em;
padding: 0.5em 0;
Expand All @@ -17,7 +26,7 @@ div.related a:hover {
color: #0095C4;
}

div.related:first-child {
div.related:first-of-type {
obulat marked this conversation as resolved.
Show resolved Hide resolved
border-top: 0;
border-bottom: 1px solid #ccc;
}
Expand Down Expand Up @@ -191,3 +200,228 @@ div.footer a:hover {
dl > dt span ~ em {
font-family: monospace, sans-serif;
}

@media (max-width: 900px) {
/* Body layout */
div.body {
min-width: 100%;
padding: 0;
font-size: 0.875rem;
}
div.bodywrapper {
margin: 0;
}
/* Typography */
div.body h1, div.body h2, div.body h3, div.body h4, div.body h5, div.body p {
font-family: SourceSansProRegular, Arial, sans-serif;
obulat marked this conversation as resolved.
Show resolved Hide resolved
}
div.body h1 {
font-size: 1.625rem;
}
div.body h2 {
font-size: 1.25rem;
}
div.body h3, div.body h4, div.body h5 {
font-size: 1rem;
}
/* Remove sidebar and top related bar */
div.related, .sphinxsidebar {
display: none;
}
/* Top navigation bar */
.mobile-nav {
display: block;
padding: 0 1rem;
height: 40px;
width: 100%;
position: fixed;
top: 0;
left: 0;
background-color: white;
box-shadow: rgba(0, 0, 0, 0.25) 0 0 2px 0;
z-index: 5;
}
.nav-content {
padding-left: 40px;
height: 40px;
display: flex;
align-items: center;
}
.nav-content img {
flex: 0 0 auto;
margin-right: 0.7rem;
}
.version_switcher_placeholder {
margin-right: 1rem;
}
.version_switcher_placeholder select {
height: 24px;
}
.nav-content #searchbox {
flex: 5 1 auto;
}
.nav-content .search {
display: flex;
flex-direction: row;
align-items: center;
box-sizing: border-box;
padding: 0 0 0 2px;
border: 1px solid #a9a9a9;
height: 24px;
}
.nav-content .search:hover {
box-shadow: 0 1px 6px 0 rgba(32,33,36,0.28);
border-color: rgba(223,225,229,0);
}
.nav-content .search input[type=text] {
border: 0;
outline: 0;
box-shadow: none;
width: 40px;
height: 100%;
flex: 1 1 auto;
}
.nav-content .search input[type=submit] {
height: 100%;
border: 0;
box-shadow: none;
outline: 1px solid #999;
}
.nav-content .search label {
border: 0;
clip: rect(0 0 0 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute !important;
obulat marked this conversation as resolved.
Show resolved Hide resolved
width: 1px;
}
obulat marked this conversation as resolved.
Show resolved Hide resolved
.nav-content .search svg {
flex: 0 0 20px;
fill: #333;
}
.toggler {
width: 40px;
height: 40px;
margin: 0;
position: absolute;
cursor: pointer;
top: 0;
left: 0;
opacity: 0;
z-index: 5;
}
.hamburger {
position: absolute;
top: 0;
left: 0;
width: 56px;
height: 40px;
padding: 0.5rem 1rem;
display: flex;
align-items: center;
justify-content: center;
}
.hamburger > div {
position: relative;
flex: none;
height: 2px;
width: 100%;
background: black;
transition: all 400ms ease;
}
.hamburger > div::before,
.hamburger > div::after {
content: '';
height: 2px;
width: 100%;
background: inherit;
position: absolute;
top: -7px;
}
.hamburger > div::after {
top: 7px;
}
.toggler:checked ~ .hamburger div {
transform: rotate(135deg);
}
.toggler:checked ~ .hamburger div::before {
transform: rotate(90deg);
}
.toggler:checked ~ .hamburger div::before,
.toggler:checked ~ .hamburger div::after {
top: 0;
}
.toggler:checked:hover ~ .hamburger div {
transform: rotate(315deg);
}

/* Sliding side menu */
.menu-wrapper {
display: block;
position: fixed;
top: 0;
z-index: 1;
left: -310px;
width: 300px;
height: 100%;
transition: all 400ms ease;
background-color: #eee;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
overflow-y: auto;
}
.menu-wrapper.open {
visibility: visible;
left: 0;
}
.menu {
padding: 40px 10px 30px 20px;
}
.menu-wrapper h3,
.menu-wrapper h4 {
margin-bottom: 0;
font-weight: normal;
}
.menu-wrapper h4 {
font-size: 1.3em;
}
.menu-wrapper h3 {
color: #444444;
font-size: 1.4em;
}
.menu-wrapper h3 + p,
.menu-wrapper h4 + p {
margin-top: 0.5rem;
}
.menu a {
font-size: smaller;
color: #444444;
text-decoration: none;
}
.menu ul {
list-style: none;
line-height: 1.4;
overflow-wrap: break-word;
padding-left: 0;
}
.menu ul ul {
margin-left: 20px;
list-style: square;
}
.menu ul li {
margin-bottom: 0.5rem;
}
.language_switcher_placeholder {
padding-top: 1.25rem;
}
.language_switcher_placeholder select {
width: 95%;
height: 24px;
}
.document {
padding-top: 40px;
position: relative;
z-index: 0;
}
}
4 changes: 2 additions & 2 deletions python_docs_theme/theme.conf
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ stylesheet = pydoctheme.css
pygments_style = sphinx

[options]
bodyfont = 'Lucida Grande', Arial, sans-serif
headfont = 'Lucida Grande', Arial, sans-serif
bodyfont = 'SourceSansProRegular','Lucida Grande', Arial, sans-serif
headfont = 'SourceSansProRegular','Lucida Grande', Arial, sans-serif
obulat marked this conversation as resolved.
Show resolved Hide resolved
footerbgcolor = white
footertextcolor = #555555
relbarbgcolor = white
Expand Down