class Meta:
ordering = ('order',)
+ @property
+ def is_separator(self):
+ return self.name == '-'
+
@property
def final_name(self):
- if self.name == '-':
+ if self.is_separator:
return mark_safe('<hr>')
if self.name:
return self.name
{% for item in menu.menuitem_set.all %}
- <li>
+ <li {% if item.is_separator %}aria-hidden="true"{% endif %}>
{% if item.has_link %}
- <a href="{{ item.final_link }}" tabindex="-1">
+ <a href="{{ item.final_link }}">
{% endif %}
{% if item.highlight %}
<em>
@import "styles/utils/mixins";
-body.is-open {
- height: 100%;
- overflow-y: hidden;
-}
-
-.l-navigation__menu {
- .scrollable {
- height: 100%;
- overflow-y: scroll;
- padding-bottom: 30px;
- }
-}
-
-.l-navigation__menu__links ul li a em {
- font-style: normal;
- color: #FFA500;
- font-weight: 600;
-}
-
.l-collections .l-books {
width: 100%;
}
#user-menu {
- //display: none;
-
+ --focus-ring: #083F4D;
+ position-area: bottom span-right;
position:absolute;
- top: 60px;
- z-index: 50;
-
- position: absolute;
width: 186px;
- top: 48px;
- right: 45px;
+ top: 8px;
/* yellow 900 */
background: #F7BA00;
+ border: none;
box-shadow: 0px 0px 20px rgba(1, 129, 137, 0.2);
border-radius: 10px;
overflow: hidden;
opacity:0;
- pointer-events: none;
- transition: 200ms opacity;
+ transition: all 350ms cubic-bezier(.0, 0, .2, 1), // $ease-out
+ display 350ms allow-discrete,
+ overlay 350ms allow-discrete;
- &.is-open {
- //display: block;
- pointer-events: all;
+ &:popover-open {
opacity: 100%;
}
}
}
+@starting-style {
+ #user-menu:popover-open {
+ opacity: 0;
+ transform: translateY(-10px);
+ }
+}
+
form {
label.required:before {
box-sizing: border-box;
}
-:focus {
- outline: $color-black auto 2px;
+:root {
+ --focus-ring: #083F4D;
+}
+
+:focus-visible {
+ outline: 2px solid var(--focus-ring);
outline-offset: 2px;
}
+html {
+ scrollbar-gutter: stable;
+}
+
html,
body {
-webkit-overflow-scrolling: auto;
overflow-y: hidden;
height: 100vh;
}
-
- &.using-mouse {
- *:focus {
- outline: 0 !important;
- }
- }
}
.visibility-hidden {
width: 150px;
right: 50px + 16px;
- opacity: 0;
- pointer-events: none;
- transition: opacity 350ms $ease-out;
z-index: $master-layer + 1;
display: none;
display: block;
}
- &.is-open {
+ &:has(.c-lang__list:popover-open) {
.c-lang__button {
.icon-arrow-down {
transform: rotate(-180deg);
}
}
- .c-lang__list {
- transform: none;
- opacity: 1;
- pointer-events: all;
- }
}
}
.c-lang__button {
+ border: 0;
+ background: none;
+ padding: 0;
+ font: inherit;
display: flex;
align-items: center;
color: $color-white;
}
}
+
.c-lang__list {
- margin-top: 10px;
+ --focus-ring: #083F4D;
+ position-area: bottom span-right;
+ position: absolute;
+ inset: auto;
+ width: 150px;
+ margin: 10px 0 0 0;
+ border: 0;
border-radius: 10px;
background-color: #F7BA00;
overflow: hidden;
transform: translateY(-10px);
opacity: 0;
- transition: all 350ms $ease-out;
- pointer-events: none;
- display: flex;
flex-direction: column;
+ transition: all 350ms $ease-out,
+ display 350ms allow-discrete,
+ overlay 350ms allow-discrete;
+ &:popover-open {
+ display: flex;
+ opacity: 1;
+ transform: none;
+ }
+
button {
display: block;
padding: 9px 20px;
}
}
}
+
+@starting-style {
+ .c-lang__list:popover-open {
+ opacity: 0;
+ transform: translateY(-10px);
+ }
+}
position: absolute;
padding: 0;
border: 0;
- outline: 0;
cursor: pointer;
font-size: 0;
background-color: transparent;
cursor: pointer;
transition: all $ease-dynamic 350ms;
background-color: $color-white;
- outline: 0;
-
font-weight: bold;
line-height: 17.6px;
display: flex;
}
.l-navigation {
+ --focus-ring: #fff;
+
max-width: 100%;
margin: 0 auto;
background-color: #083F4D;
.l-navigation__menu {
opacity: 1;
- pointer-events: all;
- }
-
- .c-lang {
- opacity: 1;
- .c-lang__button {
- pointer-events: all;
- }
+ visibility: visible;
+ pointer-events: auto;
}
}
}
background: 0;
padding: 0;
margin: 0;
- outline: 0;
position: relative;
}
-.is-open {
- .l-navigation__logo {
- z-index: $master-layer + 1;
- }
- .l-navigation__button {
- z-index: $master-layer + 1;
- }
-}
-
-
.l-naviagion__search {
width: 60%;
max-width: 580px;
border-radius: 52px;
width: 100%;
max-width: 580px;
- outline: 0;
@include rwd($break-menu) {
font-size: 18px;
position: relative;
height: 44px;
- .icon-liked {
+ .user-liked {
color: #85C7CC;
font-size: 30px;
+ line-height: 30px;
margin-right: 25px;
}
.user {
margin-right: 25px;
+ background: none;
+ border: none;
+ padding: 0;
}
}
}
.l-navigation__menu {
- position: fixed;
- top: 0; left: 0;
- width: 100%; height: 100%;
- background-color: #083F4D;
- z-index: $master-layer;
- padding-top: 50px;
- opacity: 0;
- pointer-events: none;
- transition: opacity 350ms $ease-out;
-
- @include rwd($break-menu) {
- padding-top: 93px;
- }
-
- .l-container {
- display: flex;
+ margin: 0;
+ padding: 0;
+ border: 0;
+ max-width: none;
+ max-height: none;
+ width: 100%;
+ height: 100%;
flex-direction: column;
- }
+ background-color: #083F4D;
+ opacity: 0;
+ transition: opacity 350ms $ease-out;
+ // Gdy
+ // https://caniuse.com/wf-display-animation, https://caniuse.com/wf-overlay
+ // display 350ms allow-discrete,
+ // overlay 350ms allow-discrete;
+
+ &[open] {
+ display: flex;
+ opacity: 1;
+ }
+ &:not([open]) {
+ pointer-events: none;
+ }
+ // https://caniuse.com/wf-display-animation, https://caniuse.com/wf-overlay
+ &.is-closing {
+ opacity: 0;
+ pointer-events: none;
+ }
+
+ .l-navigation__menu__top {
+ padding: 3px 0;
+ @include rwd($break-menu) {
+ padding: 12px 0;
+ }
+ }
+ .scrollable {
+ height: 100%;
+ overflow-y: auto;
+ padding-bottom: 30px;
+
+ .l-container {
+ display: flex;
+ flex-direction: column;
+ }
+ }
.l-navigation__user-bar {
width: 100%;
}
}
+body:has(dialog[open]) {
+ overflow: hidden;
+}
+
+@starting-style {
+ .l-navigation__menu[open] {
+ opacity: 0;
+ }
+}
+@media (prefers-reduced-motion: reduce) {
+ .l-navigation__menu { transition: none; }
+}
.l-navigation__menu__blocks {
position: relative;
&:hover {
text-decoration: underline;
}
+
+ em {
+ font-style: normal;
+ color: #FFA500;
+ font-weight: 600;
+ }
}
hr {
/**
* Restore the focus styles unset by the previous rule.
*/
-
-button:-moz-focusring,
-[type="button"]:-moz-focusring,
-[type="reset"]:-moz-focusring,
-[type="submit"]:-moz-focusring {
- outline: 1px dotted ButtonText;
-}
+/* WL: removed */
/**
* Correct the padding in Firefox.
// JS Menu
(function () {
- let button = $('.js-menu');
- let menu = $('.l-navigation');
- let menuLinks = menu.find('a');
-
- button.on('click', function() {
- if(!$(this).hasClass('is-active')) {
- $(this).addClass('is-active');
- menu.addClass('is-open');
- $('body').addClass('is-open');
- button.find('.bar').addClass('animate');
- menuLinks.attr('tabindex', 0);
- } else {
- $(this).removeClass('is-active');
- menu.removeClass('is-open');
- $('body').removeClass('is-open');
- button.find('.bar').removeClass('animate');
- menuLinks.attr('tabindex', -1);
- }
- });
-
- $(document).keyup(function(e) {
- if (e.keyCode === 27) {
- button.removeClass('is-active');
- menu.removeClass('is-open');
- $('body').removeClass('is-open');
- button.find('.bar').removeClass('animate');
- menuLinks.attr('tabindex', -1);
+ const dialog = document.getElementById('main-menu');
+ let buttonOn = $('.js-menu');
+ let buttonOff = $('.js-menu-close');
+
+ async function closeMenu() {
+ // Może być od razu dialog.close bez is-closing, gdy przeglądarki nadrobią
+ // https://caniuse.com/wf-display-animation, https://caniuse.com/wf-overlay
+ if (!dialog.open || dialog.classList.contains('is-closing')) return;
+ dialog.classList.add('is-closing');
+ buttonOn.find('.bar').removeClass('animate');
+ buttonOff.find('.bar').removeClass('animate');
+ await Promise.allSettled(dialog.getAnimations().map(a => a.finished));
+ dialog.close();
}
- });
-})();
-
-// User menu.
-(function() {
- let button = $('.l-navigation__actions .user');
- let menu = $('#user-menu');
- let menuLinks = menu.find('a');
-
- button.on('click', function() {
- if (!menu.hasClass('is-open')) {
- menu.addClass('is-open');
- menuLinks.attr('tabindex', 0);
- } else {
- menu.removeClass('is-open');
- menuLinks.attr('tabindex', -1)
- }
- return false;
+ dialog.addEventListener('close', () => {
+ dialog.classList.remove('is-closing');
});
- $(document).keyup(function(e) {
- if (e.keyCode === 27) {
- menu.removeClass('is-open');
- menuLinks.attr('tabindex', -1);
- }
+ document.querySelector('.js-menu').addEventListener('click', () => {
+ dialog.showModal();
+ buttonOn.find('.bar').addClass('animate');
+ buttonOff.find('.bar').addClass('animate');
});
- $(document).click(function() {
- menu.removeClass('is-open');
- menuLinks.attr('tabindex', -1);
+ dialog.querySelector('.js-menu-close').addEventListener('click', closeMenu);
+ dialog.addEventListener('cancel', e => {
+ e.preventDefault();
+ closeMenu();
});
-
})();
+
// Ebook/Audiobook Btns
(function() {
let button = $('.c-media__btn button:not(.l-button--media--full)');
window.location.reload(true);
});
- $('.c-lang').on('click', function() {
- !$(this).toggleClass('is-open');
- });
-
-
-
-
$(".c-media__settings > i").on('click', function() {
$(".c-media__settings").toggleClass('active');
{% annoy_banner_blackout %}
-<nav class="l-navigation">
+<nav class="l-navigation" aria-label="Główna">
<div class="l-container">
<a href="/" class="l-navigation__logo">
<img src="{% static "2022/images/logo.svg" %}" alt="WolneLektury.pl">
<div class="l-navigation__user-actions">
{% include 'user_actions.html' %}
</div>
- <button class="l-navigation__button js-menu" aria-label="Menu">
+ <button class="l-navigation__button js-menu"
+ aria-label="Menu" aria-haspopup="dialog" aria-controls="main-menu"
+ >
<span class="c-hamburger">
<span class="bar"></span>
</span>
</button>
</div>
- {% include 'lang-switcher.html' %}
+ </div>
+
+ <dialog id="main-menu" class="l-navigation__menu" aria-label="Menu">
+ <div class="l-navigation__menu__top">
+ <div class="l-container">
+ <a href="/" class="l-navigation__logo">
+ <img src="{% static "2022/images/logo.svg" %}" alt="WolneLektury.pl">
+ </a>
+ {% include 'lang-switcher.html' with list_id="lang-desktop" %}
+ <button class="l-navigation__button js-menu-close"
+ aria-label="Zamknij menu"
+ >
+ <span class="c-hamburger">
+ <span class="bar"></span>
+ </span>
+ </button>
+ </div>
+ </div>
- <div class="l-navigation__menu">
+
<div class="scrollable">
<div class="l-container">
<div class="l-navigation__user-bar">
<div class="l-navigation__user-actions">
- {% include 'lang-switcher.html' %}
- {% include 'user_actions.html' %}
+ {% include 'lang-switcher.html' with list_id="lang-mobile" %}
+ {% include 'user_actions.html' with hide_menu=True %}
</div>
</div>
<ul>
<li>
<a href="https://www.facebook.com/wolnelektury/"
- title="Facebook" tabindex="-1" target="_blank">
+ title="Facebook" target="_blank">
<i class="icon icon-fb" aria-hidden="true"></i>
</a>
</li>
<li>
<a href="https://www.youtube.com/c/WolneLekturyYT/"
- title="YouTube" tabindex="-1" target="_blank">
+ title="YouTube" target="_blank">
<i class="icon icon-yt" aria-hidden="true"></i>
</a>
</li>
<li>
<a href="https://www.instagram.com/wolnelektury/"
- title="Instagram" tabindex="-1" target="_blank">
+ title="Instagram" target="_blank">
<i class="icon icon-ig" aria-hidden="true"></i>
</a>
</li>
<li>
<a href="https://twitter.com/wolnelektury"
- title="Twitter" tabindex="-1" target="_blank">
+ title="Twitter" target="_blank">
<i class="icon icon-tt" aria-hidden="true"></i>
</a>
</li>
</div>
</div>
</div>
- </div>
- </div>
+ </dialog>
</nav>
{% block under-menu %}{% endblock %}
-
{% load i18n %}
+
<div class="c-lang">
- <div class="c-lang__button">
- <i class="icon icon-lang"></i>
+ <button type="button" class="c-lang__button"
+ popovertarget="{{ list_id }}">
+ <i class="icon icon-lang" aria-label="{% trans "Język:" %}"></i>
{{ LANGUAGE_CODE|language_name_local }}
- <i class="icon icon-arrow-down"></i>
- </div>
+ <i class="icon icon-arrow-down" aria-hidden="true"></i>
+ </button>
<form method="post" action="{% url 'set_language' %}">
{% csrf_token %}
- <div class="c-lang__list">
+ <div class="c-lang__list" id="{{ list_id }}" popover>
{% for lang in LANGUAGES %}
<button type="submit" lang="{{ lang.0 }}"
- name="language" value="{{ lang.0 }}" tabindex="121"
+ name="language" value="{{ lang.0 }}"
+ {% if lang.0 == LANGUAGE_CODE %}aria-current="true"{% endif %}
class="{% if lang.0 == LANGUAGE_CODE %}is-active{% endif %}">{{ lang.1 }}</button>
{% endfor %}
</div>
<ul>
<li>
<a href="https://www.facebook.com/wolnelektury/"
- title="Facebook" tabindex="-1" target="_blank">
+ title="Facebook" target="_blank">
<i class="icon icon-fb" aria-hidden="true"></i>
</a>
</li>
<li>
<a href="https://www.youtube.com/c/WolneLekturyYT/"
- title="YouTube" tabindex="-1" target="_blank">
+ title="YouTube" target="_blank">
<i class="icon icon-yt" aria-hidden="true"></i>
</a>
</li>
<li>
<a href="https://www.instagram.com/wolnelektury/"
- title="Instagram" tabindex="-1" target="_blank">
+ title="Instagram" target="_blank">
<i class="icon icon-ig" aria-hidden="true"></i>
</a>
</li>
<li>
<a href="https://twitter.com/wolnelektury"
- title="Twitter" tabindex="-1" target="_blank">
+ title="Twitter" target="_blank">
<i class="icon icon-tt" aria-hidden="true"></i>
</a>
</li>
{% load i18n static %}
{% if request.user.is_authenticated %}
- <a href="/ludzie/polka/"><i class="icon icon-liked"></i></a>
- <div id="user-menu">
+<a class="user-liked" href="/ludzie/polka/" aria-label="Półka"><i class="icon icon-liked"></i></a>
+ {% if hide_menu %}
+ <a href="{% url 'user_settings' %}" class="user" aria-label="{% trans "Twoje konto" %}">
+ {% else %}
+ <button type="button" class="user"
+ popovertarget="user-menu"
+ aria-label="{% trans "Menu konta" %}">
+ {% endif %}
+ {% if request.user.is_staff %}
+ <img src="{% static '2022/images/icons/user-staff.svg' %}">
+ {% elif request.user.membership %}
+ <img src="{% static '2022/images/icons/user-vip.svg' %}">
+ {% else %}
+ <img src="{% static '2022/images/icons/user.svg' %}">
+ {% endif %}
+ {% if hide_menu %}
+ </a>
+ {% else %}
+ </button>
+ {% endif %}
+ {% if not hide_menu %}
+ <div id="user-menu" popover>
<ul>
<li>
- <a href="{% url 'user_settings' %}" tabindex="-1">
+ <a href="{% url 'user_settings' %}">
<strong>
{{ request.user.username }}
</strong>
</a>
</li>
{% if request.user.is_staff %}
- <li><a href="{% url 'admin:index' %}" tabindex="-1">{% trans "Administracja" %}</a></li>
- <li><a class='edit-links-toggle' href="#" tabindex="-1">{% trans "Edytuj" %}</a></li>
+ <li><a href="{% url 'admin:index' %}">{% trans "Administracja" %}</a></li>
+ <li><a class='edit-links-toggle' href="#">{% trans "Edytuj" %}</a></li>
{% endif %}
{% if request.user.membership %}
<li><a href="{% url 'club_join' %}">{% trans "Wspierasz Wolne Lektury, dziękujemy!" %}</a></li>
{% endif %}
- <li><a href="{% url 'logout' %}?next={% block logout %}{{ request.get_full_path }}{% endblock %}" tabindex="-1">{% trans "Wyloguj się" %}</a></li>
+ <li><a href="{% url 'logout' %}?next={% block logout %}{{ request.get_full_path }}{% endblock %}">{% trans "Wyloguj się" %}</a></li>
</ul>
</div>
- <a href="{% url 'user_settings' %}" class="user">
- {% if request.user.is_staff %}
- <img src="{% static '2022/images/icons/user-staff.svg' %}">
- {% elif request.user.membership %}
- <img src="{% static '2022/images/icons/user-vip.svg' %}">
- {% else %}
- <img src="{% static '2022/images/icons/user.svg' %}">
- {% endif %}
- </a>
+ {% endif %}
{% else %}
<div class="l-navigation__login">
<a id="login-link" href='{% url 'login' %}?next={{ request.path }}'>{% trans "Zaloguj się" %}</a>