forked from mirrors/bookwyrm
Front-end: Fix Safari details display and enhance dropdown on mobile
This commit is contained in:
parent
f5b7fcd0c7
commit
355405daa3
3 changed files with 159 additions and 11 deletions
|
@ -93,6 +93,10 @@ body {
|
|||
display: inline !important;
|
||||
}
|
||||
|
||||
|
||||
/** File input styles
|
||||
******************************************************************************/
|
||||
|
||||
input[type=file]::file-selector-button {
|
||||
-moz-appearance: none;
|
||||
-webkit-appearance: none;
|
||||
|
@ -119,17 +123,12 @@ input[type=file]::file-selector-button:hover {
|
|||
color: #363636;
|
||||
}
|
||||
|
||||
details .dropdown-menu {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
details.dropdown[open] summary.dropdown-trigger::before {
|
||||
content: "";
|
||||
position: fixed;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
/** General `details` element styles
|
||||
******************************************************************************/
|
||||
|
||||
summary::-webkit-details-marker {
|
||||
display: none;
|
||||
}
|
||||
|
||||
summary::marker {
|
||||
|
@ -147,6 +146,55 @@ summary::marker {
|
|||
margin-top: 1em;
|
||||
}
|
||||
|
||||
/** Details dropdown
|
||||
******************************************************************************/
|
||||
|
||||
details.dropdown[open] summary.dropdown-trigger::before {
|
||||
content: "";
|
||||
position: fixed;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
details .dropdown-menu {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
details .dropdown-menu button {
|
||||
/* Fix weird Safari defaults */
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
details.dropdown .dropdown-menu button:focus-visible,
|
||||
details.dropdown .dropdown-menu a:focus-visible {
|
||||
outline-style: auto;
|
||||
outline-offset: -2px;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 768px) {
|
||||
details.dropdown[open] summary.dropdown-trigger::before {
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
z-index: 30;
|
||||
}
|
||||
details .dropdown-menu {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex !important;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
pointer-events: none;
|
||||
z-index: 100;
|
||||
}
|
||||
details .dropdown-menu > * {
|
||||
pointer-events: all;
|
||||
}
|
||||
}
|
||||
|
||||
/** Shelving
|
||||
******************************************************************************/
|
||||
|
||||
|
|
|
@ -51,6 +51,12 @@ let BookWyrm = new class {
|
|||
'click',
|
||||
this.duplicateInput.bind(this)
|
||||
|
||||
))
|
||||
document.querySelectorAll('details.dropdown')
|
||||
.forEach(node => node.addEventListener(
|
||||
'toggle',
|
||||
this.handleDetailsDropdown.bind(this)
|
||||
|
||||
))
|
||||
}
|
||||
|
||||
|
@ -482,4 +488,98 @@ let BookWyrm = new class {
|
|||
|
||||
textareaEl.parentNode.appendChild(copyButtonEl)
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the details dropdown component.
|
||||
*
|
||||
* @param {Event} event - Event fired by a `details` element
|
||||
* with the `dropdown` class name, on toggle.
|
||||
* @return {undefined}
|
||||
*/
|
||||
handleDetailsDropdown(event) {
|
||||
const detailsElement = event.target;
|
||||
const summaryElement = detailsElement.querySelector('summary');
|
||||
const menuElement = detailsElement.querySelector('.dropdown-menu');
|
||||
const htmlElement = document.querySelector('html');
|
||||
|
||||
if (detailsElement.open) {
|
||||
// Focus first menu element
|
||||
menuElement.querySelectorAll(
|
||||
'a[href]:not([disabled]), button:not([disabled])'
|
||||
)[0].focus();
|
||||
// Enable focus trap
|
||||
menuElement.addEventListener('keydown', this.handleFocusTrap);
|
||||
// Close on Esc
|
||||
detailsElement.addEventListener('keydown', handleEscKey);
|
||||
|
||||
// Clip page if Mobile
|
||||
if (this.isMobile()) {
|
||||
htmlElement.classList.add('is-clipped');
|
||||
}
|
||||
} else {
|
||||
summaryElement.focus();
|
||||
// Disable focus trap
|
||||
menuElement.removeEventListener('keydown', this.handleFocusTrap);
|
||||
|
||||
// Unclip page
|
||||
if (this.isMobile()) {
|
||||
htmlElement.classList.remove('is-clipped');
|
||||
}
|
||||
}
|
||||
|
||||
function handleEscKey(event) {
|
||||
if (event.key !== 'Escape') {
|
||||
return;
|
||||
}
|
||||
|
||||
summaryElement.click();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if windows matches mobile media query.
|
||||
*
|
||||
* @return {Boolean}
|
||||
*/
|
||||
isMobile() {
|
||||
return window.matchMedia("(max-width: 768px)").matches;
|
||||
}
|
||||
|
||||
/**
|
||||
* Focus trap handler
|
||||
*
|
||||
* @param {Event} event - Keydown event.
|
||||
* @return {undefined}
|
||||
*/
|
||||
handleFocusTrap(event) {
|
||||
if (event.key !== 'Tab') {
|
||||
return;
|
||||
}
|
||||
|
||||
const focusableEls = event.currentTarget.querySelectorAll(
|
||||
[
|
||||
'a[href]:not([disabled])',
|
||||
'button:not([disabled])',
|
||||
'textarea:not([disabled])',
|
||||
'input:not([type="hidden"]):not([disabled])',
|
||||
'select:not([disabled])',
|
||||
'details:not([disabled])',
|
||||
'[tabindex]:not([tabindex="-1"]):not([disabled])'
|
||||
].join(',')
|
||||
);
|
||||
const firstFocusableEl = focusableEls[0];
|
||||
const lastFocusableEl = focusableEls[focusableEls.length - 1];
|
||||
|
||||
if (event.shiftKey ) /* Shift + tab */ {
|
||||
if (document.activeElement === firstFocusableEl) {
|
||||
lastFocusableEl.focus();
|
||||
event.preventDefault();
|
||||
}
|
||||
} else /* Tab */ {
|
||||
if (document.activeElement === lastFocusableEl) {
|
||||
firstFocusableEl.focus();
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
}();
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
{% block dropdown-trigger %}{% endblock %}
|
||||
</summary>
|
||||
|
||||
<div class="dropdown-menu control">
|
||||
<div class="dropdown-menu">
|
||||
<ul
|
||||
id="menu_options_{{ uuid }}"
|
||||
class="dropdown-content p-0 is-clipped"
|
||||
|
|
Loading…
Reference in a new issue