UNPKG

@uppy/dashboard

Version:

Universal UI plugin for Uppy.

65 lines (64 loc) 3.04 kB
// @ts-ignore untyped import FOCUSABLE_ELEMENTS from '@uppy/utils/lib/FOCUSABLE_ELEMENTS'; import toArray from '@uppy/utils/lib/toArray'; import getActiveOverlayEl from './getActiveOverlayEl.js'; function focusOnFirstNode(event, nodes) { const node = nodes[0]; if (node) { node.focus(); event.preventDefault(); } } function focusOnLastNode(event, nodes) { const node = nodes[nodes.length - 1]; if (node) { node.focus(); event.preventDefault(); } } // ___Why not just use (focusedItemIndex === -1)? // Firefox thinks <ul> is focusable, but we don't have <ul>s in our FOCUSABLE_ELEMENTS. Which means that if we tab into // the <ul>, code will think that we are not in the active overlay, and we should focusOnFirstNode() of the currently // active overlay! // [Practical check] if we use (focusedItemIndex === -1), instagram provider in firefox will never get focus on its pics // in the <ul>. function isFocusInOverlay(activeOverlayEl) { return activeOverlayEl.contains(document.activeElement); } function trapFocus(event, activeOverlayType, dashboardEl) { const activeOverlayEl = getActiveOverlayEl(dashboardEl, activeOverlayType); const focusableNodes = toArray(activeOverlayEl.querySelectorAll(FOCUSABLE_ELEMENTS)); const focusedItemIndex = focusableNodes.indexOf(document.activeElement); // If we pressed tab, and focus is not yet within the current overlay - focus on // the first element within the current overlay. // This is a safety measure (for when user returns from another tab e.g.), most // plugins will try to focus on some important element as it loads. if (!isFocusInOverlay(activeOverlayEl)) { focusOnFirstNode(event, focusableNodes); // If we pressed shift + tab, and we're on the first element of a modal } else if (event.shiftKey && focusedItemIndex === 0) { focusOnLastNode(event, focusableNodes); // If we pressed tab, and we're on the last element of the modal } else if (!event.shiftKey && focusedItemIndex === focusableNodes.length - 1) { focusOnFirstNode(event, focusableNodes); } } // Traps focus inside of the currently open overlay (e.g. Dashboard, or e.g. Instagram), // never lets focus disappear from the modal. export { trapFocus as forModal }; // Traps focus inside of the currently open overlay, unless overlay is null - then let the user tab away. export function forInline(event, activeOverlayType, dashboardEl) { // ___When we're in the bare 'Drop files here, paste, browse or import from' screen if (activeOverlayType === null) { // Do nothing and let the browser handle it, user can tab away from Uppy to other elements on the page // ___When there is some overlay with 'Done' button } else { // Trap the focus inside this overlay! // User can close the overlay (click 'Done') if they want to travel away from Uppy. trapFocus(event, activeOverlayType, dashboardEl); } }