From 4ed4278826d3e88bc544f22159aa6bb0b16fbe75 Mon Sep 17 00:00:00 2001 From: Joachim Date: Sat, 27 Nov 2021 19:18:20 +0100 Subject: [PATCH 01/13] Tidy header for non-authenticated visitors with the help of a login modal --- bookwyrm/static/css/bookwyrm.css | 16 +++++++ bookwyrm/static/js/bookwyrm.js | 74 ++++++++++++++++++++++++++++++++ bookwyrm/templates/layout.html | 71 +++++++++++++++++++++--------- 3 files changed, 141 insertions(+), 20 deletions(-) diff --git a/bookwyrm/static/css/bookwyrm.css b/bookwyrm/static/css/bookwyrm.css index 0d280fd53..81f0cf1a8 100644 --- a/bookwyrm/static/css/bookwyrm.css +++ b/bookwyrm/static/css/bookwyrm.css @@ -25,10 +25,26 @@ body { overflow-x: auto; } +.modal-card:focus { + outline-style: auto; +} +.modal-card:focus:not(:focus-visible) { + outline-style: initial; +} +.modal-card:focus-visible { + outline-style: auto; +} + .modal-card.is-fullwidth { min-width: 75% !important; } +@media only screen and (min-width: 769px) { + .modal-card.is-thin { + width: 350px !important; + } +} + .modal-card-body { max-height: 70vh; } diff --git a/bookwyrm/static/js/bookwyrm.js b/bookwyrm/static/js/bookwyrm.js index 2d5b88adc..5f062f786 100644 --- a/bookwyrm/static/js/bookwyrm.js +++ b/bookwyrm/static/js/bookwyrm.js @@ -45,6 +45,12 @@ let BookWyrm = new class { 'change', this.disableIfTooLarge.bind(this) )); + + document.querySelectorAll('button[data-modal-open]') + .forEach(node => node.addEventListener( + 'click', + this.handleModalButton.bind(this) + )); } /** @@ -368,4 +374,72 @@ let BookWyrm = new class { ); } } + + handleModalButton(element) { + const modalButton = element.currentTarget; + const targetModalId = modalButton.dataset.modalOpen; + const htmlElement = document.querySelector('html'); + + // Helper functions + function handleModalOpen(modalElement) { + htmlElement.classList.add('is-clipped'); + modalElement.classList.add('is-active'); + modalElement.getElementsByClassName('modal-card')[0].focus(); + + const closeButtons = modalElement.querySelectorAll("[data-modal-close]"); + closeButtons.forEach((button) => { + button.addEventListener( + 'click', + function() { handleModalClose(modalElement) }, + ); + }); + + document.addEventListener( + 'keydown', + function(event) { + if (event.key === 'Escape') { + handleModalClose(modalElement); + } + }, + ); + + modalElement.addEventListener('keydown', handleFocusTrap) + } + + function handleModalClose(modalElement) { + modalElement.removeEventListener('keydown', handleFocusTrap) + htmlElement.classList.remove('is-clipped'); + modalElement.classList.remove('is-active'); + modalButton.focus(); + } + + function handleFocusTrap(event) { + const focusableEls = event.currentTarget.querySelectorAll('a[href]:not([disabled]), button:not([disabled]), textarea:not([disabled]), input[type="text"]:not([disabled]), input[type="radio"]:not([disabled]), input[type="checkbox"]:not([disabled]), select:not([disabled])'); + const firstFocusableEl = focusableEls[0]; + const lastFocusableEl = focusableEls[focusableEls.length - 1]; + + if (event.key !== 'Tab') { + return; + } + + if (event.shiftKey ) /* shift + tab */ { + if (document.activeElement === firstFocusableEl) { + lastFocusableEl.focus(); + event.preventDefault(); + } + } else /* tab */ { + if (document.activeElement === lastFocusableEl) { + firstFocusableEl.focus(); + event.preventDefault(); + } + } + } + + const modal = document.getElementById(targetModalId); + if (modal) { + // Open the modal + handleModalOpen(modal); + } + } + }(); diff --git a/bookwyrm/templates/layout.html b/bookwyrm/templates/layout.html index f2d04f961..4a7457dca 100644 --- a/bookwyrm/templates/layout.html +++ b/bookwyrm/templates/layout.html @@ -158,28 +158,14 @@ {% endwith %} - {% else %} + {% endif %} + + {% if not request.user.is_authenticated %} @@ -258,6 +244,51 @@ +{# Login modal #} +{% if not request.user.is_authenticated %} + +{% endif %} + From 89bbf005c39009bd9285cb87a671109de4150daa Mon Sep 17 00:00:00 2001 From: Joachim Date: Sat, 27 Nov 2021 19:19:09 +0100 Subject: [PATCH 02/13] Add an accessibility helper This will display a default outline specifically for keyboard users (and some inputs) --- bookwyrm/static/css/bookwyrm.css | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/bookwyrm/static/css/bookwyrm.css b/bookwyrm/static/css/bookwyrm.css index 81f0cf1a8..333ddf80f 100644 --- a/bookwyrm/static/css/bookwyrm.css +++ b/bookwyrm/static/css/bookwyrm.css @@ -8,6 +8,11 @@ body { flex-direction: column; } +/* Better accessibility for keyboard users */ +*:focus-visible { + outline-style: auto !important; +} + .image { overflow: hidden; } From c924f578e5b1555d32ceebfa7aff3fc615578d4d Mon Sep 17 00:00:00 2001 From: Joachim Date: Sun, 28 Nov 2021 18:26:01 +0100 Subject: [PATCH 03/13] Fix linting errors --- bookwyrm/static/css/bookwyrm.css | 4 ++++ bookwyrm/static/js/bookwyrm.js | 12 +++++++++++- bookwyrm/templates/layout.html | 2 +- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/bookwyrm/static/css/bookwyrm.css b/bookwyrm/static/css/bookwyrm.css index 333ddf80f..6a2eae348 100644 --- a/bookwyrm/static/css/bookwyrm.css +++ b/bookwyrm/static/css/bookwyrm.css @@ -30,15 +30,19 @@ body { overflow-x: auto; } +/* stylelint-disable no-descending-specificity */ .modal-card:focus { outline-style: auto; } + .modal-card:focus:not(:focus-visible) { outline-style: initial; } + .modal-card:focus-visible { outline-style: auto; } +/* stylelint-disable no-descending-specificity */ .modal-card.is-fullwidth { min-width: 75% !important; diff --git a/bookwyrm/static/js/bookwyrm.js b/bookwyrm/static/js/bookwyrm.js index 5f062f786..8c2f107bc 100644 --- a/bookwyrm/static/js/bookwyrm.js +++ b/bookwyrm/static/js/bookwyrm.js @@ -414,7 +414,17 @@ let BookWyrm = new class { } function handleFocusTrap(event) { - const focusableEls = event.currentTarget.querySelectorAll('a[href]:not([disabled]), button:not([disabled]), textarea:not([disabled]), input[type="text"]:not([disabled]), input[type="radio"]:not([disabled]), input[type="checkbox"]:not([disabled]), select:not([disabled])'); + const focusableEls = event.currentTarget.querySelectorAll( + [ + 'a[href]:not([disabled])', + 'button:not([disabled])', + 'textarea:not([disabled])', + 'input[type="text"]:not([disabled])', + 'input[type="radio"]:not([disabled])', + 'input[type="checkbox"]:not([disabled])', + 'select:not([disabled])' + ].join(',') + ); const firstFocusableEl = focusableEls[0]; const lastFocusableEl = focusableEls[focusableEls.length - 1]; diff --git a/bookwyrm/templates/layout.html b/bookwyrm/templates/layout.html index 4a7457dca..7296f136c 100644 --- a/bookwyrm/templates/layout.html +++ b/bookwyrm/templates/layout.html @@ -285,7 +285,7 @@ - {% endif %} From a688c73b79942cbef9fdabfa0faa42b92cee3c81 Mon Sep 17 00:00:00 2001 From: Joachim Date: Sun, 28 Nov 2021 18:28:49 +0100 Subject: [PATCH 04/13] Fix stylelint rule --- bookwyrm/static/css/bookwyrm.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/static/css/bookwyrm.css b/bookwyrm/static/css/bookwyrm.css index 6a2eae348..0b2f98bae 100644 --- a/bookwyrm/static/css/bookwyrm.css +++ b/bookwyrm/static/css/bookwyrm.css @@ -42,7 +42,7 @@ body { .modal-card:focus-visible { outline-style: auto; } -/* stylelint-disable no-descending-specificity */ +/* stylelint-enable no-descending-specificity */ .modal-card.is-fullwidth { min-width: 75% !important; From 3816b0aa5729a4367559e793ff25b6c8a237ab77 Mon Sep 17 00:00:00 2001 From: Joachim Date: Sun, 28 Nov 2021 18:34:54 +0100 Subject: [PATCH 05/13] Better JS --- bookwyrm/static/js/bookwyrm.js | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/bookwyrm/static/js/bookwyrm.js b/bookwyrm/static/js/bookwyrm.js index 8c2f107bc..203d73d7c 100644 --- a/bookwyrm/static/js/bookwyrm.js +++ b/bookwyrm/static/js/bookwyrm.js @@ -379,6 +379,11 @@ let BookWyrm = new class { const modalButton = element.currentTarget; const targetModalId = modalButton.dataset.modalOpen; const htmlElement = document.querySelector('html'); + const modal = document.getElementById(targetModalId); + + if (!modal) { + return; + } // Helper functions function handleModalOpen(modalElement) { @@ -387,10 +392,11 @@ let BookWyrm = new class { modalElement.getElementsByClassName('modal-card')[0].focus(); const closeButtons = modalElement.querySelectorAll("[data-modal-close]"); + closeButtons.forEach((button) => { button.addEventListener( - 'click', - function() { handleModalClose(modalElement) }, + 'click', + function() { handleModalClose(modalElement) } ); }); @@ -400,7 +406,7 @@ let BookWyrm = new class { if (event.key === 'Escape') { handleModalClose(modalElement); } - }, + } ); modalElement.addEventListener('keydown', handleFocusTrap) @@ -432,24 +438,20 @@ let BookWyrm = new class { return; } - if (event.shiftKey ) /* shift + tab */ { + if (event.shiftKey ) /* Shift + tab */ { if (document.activeElement === firstFocusableEl) { lastFocusableEl.focus(); event.preventDefault(); } - } else /* tab */ { + } else /* Tab */ { if (document.activeElement === lastFocusableEl) { firstFocusableEl.focus(); event.preventDefault(); } } } - - const modal = document.getElementById(targetModalId); - if (modal) { - // Open the modal - handleModalOpen(modal); - } + + // Open modal + handleModalOpen(modal); } - }(); From bf5cb898ef30dc11ce979bd0a77816af7f0a322c Mon Sep 17 00:00:00 2001 From: Joachim Date: Sun, 28 Nov 2021 21:45:35 +0100 Subject: [PATCH 06/13] Apply review suggestion --- bookwyrm/static/js/bookwyrm.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bookwyrm/static/js/bookwyrm.js b/bookwyrm/static/js/bookwyrm.js index 203d73d7c..868a75f46 100644 --- a/bookwyrm/static/js/bookwyrm.js +++ b/bookwyrm/static/js/bookwyrm.js @@ -425,10 +425,10 @@ let BookWyrm = new class { 'a[href]:not([disabled])', 'button:not([disabled])', 'textarea:not([disabled])', - 'input[type="text"]:not([disabled])', - 'input[type="radio"]:not([disabled])', - 'input[type="checkbox"]:not([disabled])', - 'select: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]; From 9ec4ad6b319334bbb6bd647987421c37487afcb6 Mon Sep 17 00:00:00 2001 From: Joachim Date: Sun, 28 Nov 2021 21:46:32 +0100 Subject: [PATCH 07/13] Apply review suggestion --- bookwyrm/static/js/bookwyrm.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bookwyrm/static/js/bookwyrm.js b/bookwyrm/static/js/bookwyrm.js index 868a75f46..4a2f882c0 100644 --- a/bookwyrm/static/js/bookwyrm.js +++ b/bookwyrm/static/js/bookwyrm.js @@ -420,6 +420,10 @@ let BookWyrm = new class { } function handleFocusTrap(event) { + if (event.key !== 'Tab') { + return; + } + const focusableEls = event.currentTarget.querySelectorAll( [ 'a[href]:not([disabled])', @@ -434,10 +438,6 @@ let BookWyrm = new class { const firstFocusableEl = focusableEls[0]; const lastFocusableEl = focusableEls[focusableEls.length - 1]; - if (event.key !== 'Tab') { - return; - } - if (event.shiftKey ) /* Shift + tab */ { if (document.activeElement === firstFocusableEl) { lastFocusableEl.focus(); From 84b5c2da4eec9eaace8a1bc4bc0ae69c8799feef Mon Sep 17 00:00:00 2001 From: Joachim Date: Sun, 28 Nov 2021 22:10:15 +0100 Subject: [PATCH 08/13] Documentation --- bookwyrm/static/js/bookwyrm.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/bookwyrm/static/js/bookwyrm.js b/bookwyrm/static/js/bookwyrm.js index 4a2f882c0..352bb7c7b 100644 --- a/bookwyrm/static/js/bookwyrm.js +++ b/bookwyrm/static/js/bookwyrm.js @@ -375,8 +375,16 @@ let BookWyrm = new class { } } - handleModalButton(element) { - const modalButton = element.currentTarget; + /** + * Handle the modal component. + * + * @param {Event} event - Event fired by an element + * with the `data-modal-open` attribute + * pointing to a modal by its id. + * @return {undefined} + */ + handleModalButton(event) { + const modalButton = event.currentTarget; const targetModalId = modalButton.dataset.modalOpen; const htmlElement = document.querySelector('html'); const modal = document.getElementById(targetModalId); From 2544ea12c77c6f46621dfa45c51a808ca382f46d Mon Sep 17 00:00:00 2001 From: Joachim Date: Fri, 17 Dec 2021 17:00:10 +0100 Subject: [PATCH 09/13] Revert changes on layout --- bookwyrm/static/js/bookwyrm.js | 3 ++ bookwyrm/templates/layout.html | 71 ++++++++++------------------------ 2 files changed, 23 insertions(+), 51 deletions(-) diff --git a/bookwyrm/static/js/bookwyrm.js b/bookwyrm/static/js/bookwyrm.js index ba6cce043..e7586072d 100644 --- a/bookwyrm/static/js/bookwyrm.js +++ b/bookwyrm/static/js/bookwyrm.js @@ -427,6 +427,9 @@ let BookWyrm = new class { * with the `data-modal-open` attribute * pointing to a modal by its id. * @return {undefined} + * + * See https://github.com/bookwyrm-social/bookwyrm/pull/1633 + * for information about using the modal. */ handleModalButton(event) { const modalButton = event.currentTarget; diff --git a/bookwyrm/templates/layout.html b/bookwyrm/templates/layout.html index 4447754b1..25aaf1b6b 100644 --- a/bookwyrm/templates/layout.html +++ b/bookwyrm/templates/layout.html @@ -158,14 +158,28 @@ {% endwith %} - {% endif %} - - {% if not request.user.is_authenticated %} + {% else %} @@ -244,51 +258,6 @@ -{# Login modal #} -{% if not request.user.is_authenticated %} - -{% endif %} - From f300104c4d71b79d606a886dc6926a1f42de21b0 Mon Sep 17 00:00:00 2001 From: Joachim Date: Fri, 17 Dec 2021 17:29:46 +0100 Subject: [PATCH 10/13] Add reset button style --- bookwyrm/static/css/bookwyrm.css | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/bookwyrm/static/css/bookwyrm.css b/bookwyrm/static/css/bookwyrm.css index 5772c4b8a..5b171dab4 100644 --- a/bookwyrm/static/css/bookwyrm.css +++ b/bookwyrm/static/css/bookwyrm.css @@ -8,6 +8,36 @@ body { flex-direction: column; } +button { + border: none; + margin: 0; + padding: 0; + width: auto; + overflow: visible; + + background: transparent; + + /* inherit font & color from ancestor */ + color: inherit; + font: inherit; + + /* Normalize `line-height`. Cannot be changed from `normal` in Firefox 4+. */ + line-height: normal; + + /* Corrects font smoothing for webkit */ + -webkit-font-smoothing: inherit; + -moz-osx-font-smoothing: inherit; + + /* Corrects inability to style clickable `input` types in iOS */ + -webkit-appearance: none; +} + +button::-moz-focus-inner { + /* Remove excess padding and border in Firefox 4+ */ + border: 0; + padding: 0; +} + /* Better accessibility for keyboard users */ *:focus-visible { outline-style: auto !important; From ce0e2eb61a5d8201679bdb0a498af0294b666493 Mon Sep 17 00:00:00 2001 From: Joachim Date: Fri, 17 Dec 2021 17:30:14 +0100 Subject: [PATCH 11/13] Handle navbar alignment thank to Bulma helper classes --- bookwyrm/templates/layout.html | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/bookwyrm/templates/layout.html b/bookwyrm/templates/layout.html index 25aaf1b6b..2380c4d34 100644 --- a/bookwyrm/templates/layout.html +++ b/bookwyrm/templates/layout.html @@ -36,7 +36,7 @@ -