CI / build (push) Failing after 6m2s
Introduce a Node build system for minified CSS/JS with content hashes, add PWA support, i18n helpers, accessibility improvements, and more translatable strings. Move theme configuration from bookmarks to localStorage, add Playwright tests, and set up CI workflows.
67 lines
2.0 KiB
JavaScript
67 lines
2.0 KiB
JavaScript
// =====================================================================
|
|
// Accessibility helpers for Shaarli Pro modals and overlays.
|
|
// =====================================================================
|
|
(function (root) {
|
|
'use strict';
|
|
|
|
const FOCUSABLE_SELECTORS = [
|
|
'a[href]',
|
|
'button:not([disabled])',
|
|
'input:not([disabled])',
|
|
'select:not([disabled])',
|
|
'textarea:not([disabled])',
|
|
'[tabindex]:not([tabindex="-1"])'
|
|
].join(', ');
|
|
|
|
/**
|
|
* Return a focusable element inside a container.
|
|
*/
|
|
function getFocusable(container, first) {
|
|
if (!container) return null;
|
|
const elements = Array.prototype.slice.call(container.querySelectorAll(FOCUSABLE_SELECTORS));
|
|
return first ? elements[0] : elements[elements.length - 1];
|
|
}
|
|
|
|
/**
|
|
* Move focus to the first focusable element inside a container.
|
|
*/
|
|
function focusFirst(container) {
|
|
const el = getFocusable(container, true);
|
|
if (el) el.focus();
|
|
}
|
|
|
|
/**
|
|
* Keep keyboard focus inside a container while it is open.
|
|
* Returns a cleanup function that removes the listener.
|
|
*/
|
|
function trapFocus(container) {
|
|
if (!container) return function () {};
|
|
|
|
function handleKey(e) {
|
|
if (e.key !== 'Tab') return;
|
|
const first = getFocusable(container, true);
|
|
const last = getFocusable(container, false);
|
|
if (!first || !last) return;
|
|
|
|
if (e.shiftKey && document.activeElement === first) {
|
|
e.preventDefault();
|
|
last.focus();
|
|
} else if (!e.shiftKey && document.activeElement === last) {
|
|
e.preventDefault();
|
|
first.focus();
|
|
}
|
|
}
|
|
|
|
container.addEventListener('keydown', handleKey);
|
|
return function () {
|
|
container.removeEventListener('keydown', handleKey);
|
|
};
|
|
}
|
|
|
|
root.ShaarliProA11y = {
|
|
focusFirst: focusFirst,
|
|
trapFocus: trapFocus,
|
|
getFocusable: getFocusable
|
|
};
|
|
}(window));
|