fix(a11y): leverage native :focus-visible in CSS

This commit is contained in:
Sam Potts
2023-03-11 21:15:32 +11:00
parent e17d0220c0
commit 0202e8efb0
22 changed files with 39 additions and 136 deletions

View File

@ -379,7 +379,6 @@ const defaults = {
supported: 'plyr--airplay-supported',
active: 'plyr--airplay-active',
},
tabFocus: 'plyr__tab-focus',
previewThumbnails: {
// Tooltip thumbs
thumbContainer: 'plyr__preview-thumb',

8
src/js/controls.js vendored
View File

@ -1106,7 +1106,7 @@ const controls = {
},
// Focus the first menu item in a given (or visible) menu
focusFirstMenuItem(pane, tabFocus = false) {
focusFirstMenuItem(pane, focusVisible = false) {
if (this.elements.settings.popup.hidden) {
return;
}
@ -1119,7 +1119,7 @@ const controls = {
const firstItem = target.querySelector('[role^="menuitem"]');
setFocus.call(this, firstItem, tabFocus);
setFocus.call(this, firstItem, focusVisible);
},
// Show/hide menu
@ -1196,7 +1196,7 @@ const controls = {
},
// Show a panel in the menu
showMenuPanel(type = '', tabFocus = false) {
showMenuPanel(type = '', focusVisible = false) {
const target = this.elements.container.querySelector(`#plyr-settings-${this.id}-${type}`);
// Nothing to show, bail
@ -1247,7 +1247,7 @@ const controls = {
toggleHidden(target, false);
// Focus the first item
controls.focusFirstMenuItem.call(this, target, tabFocus);
controls.focusFirstMenuItem.call(this, target, focusVisible);
},
// Set the download URL

View File

@ -21,7 +21,6 @@ class Listeners {
this.handleKey = this.handleKey.bind(this);
this.toggleMenu = this.toggleMenu.bind(this);
this.setTabFocus = this.setTabFocus.bind(this);
this.firstTouch = this.firstTouch.bind(this);
}
@ -194,57 +193,6 @@ class Listeners {
toggleClass(elements.container, player.config.classNames.isTouch, true);
};
setTabFocus = (event) => {
const { player } = this;
const { elements } = player;
const { key, type, timeStamp } = event;
clearTimeout(this.focusTimer);
// Ignore any key other than tab
if (type === 'keydown' && key !== 'Tab') {
return;
}
// Store reference to event timeStamp
if (type === 'keydown') {
this.lastKeyDown = timeStamp;
}
// Remove current classes
const removeCurrent = () => {
const className = player.config.classNames.tabFocus;
const current = getElements.call(player, `.${className}`);
toggleClass(current, className, false);
};
// Determine if a key was pressed to trigger this event
const wasKeyDown = timeStamp - this.lastKeyDown <= 20;
// Ignore focus events if a key was pressed prior
if (type === 'focus' && !wasKeyDown) {
return;
}
// Remove all current
removeCurrent();
// Delay the adding of classname until the focus has changed
// This event fires before the focusin event
if (type !== 'focusout') {
this.focusTimer = setTimeout(() => {
const focused = document.activeElement;
// Ignore if current focus element isn't inside the player
if (!elements.container.contains(focused)) {
return;
}
toggleClass(document.activeElement, player.config.classNames.tabFocus, true);
}, 10);
}
};
// Global window & document listeners
global = (toggle = true) => {
const { player } = this;
@ -259,9 +207,6 @@ class Listeners {
// Detect touch by events
once.call(player, document.body, 'touchstart', this.firstTouch);
// Tab focus detection
toggleListener.call(player, document.body, 'keydown focus blur focusout', this.setTabFocus, toggle, false, true);
};
// Container listeners

View File

@ -268,16 +268,11 @@ export function getElement(selector) {
}
// Set focus and tab focus class
export function setFocus(element = null, tabFocus = false) {
export function setFocus(element = null, focusVisible = false) {
if (!is.element(element)) {
return;
}
// Set regular focus
element.focus({ preventScroll: true });
// If we want to mimic keyboard focus via tab
if (tabFocus) {
toggleClass(element, this.config.classNames.tabFocus);
}
element.focus({ preventScroll: true, focusVisible });
}

View File

@ -28,8 +28,8 @@
}
// Tab focus
&.plyr__tab-focus {
@include plyr-tab-focus;
&:focus-visible {
@include plyr-focus-visible;
}
}

View File

@ -100,7 +100,7 @@
right: calc((#{$plyr-control-padding} * 1.5) - #{$plyr-menu-item-arrow-size});
}
&.plyr__tab-focus::after,
&:focus-visible::after,
&:hover::after {
border-left-color: currentColor;
}
@ -132,7 +132,7 @@
top: 100%;
}
&.plyr__tab-focus::after,
&:focus-visible::after,
&:hover::after {
border-right-color: currentColor;
}
@ -181,7 +181,7 @@
}
}
&.plyr__tab-focus::before,
&:focus-visible::before,
&:hover::before {
background: rgba($plyr-color-gray-900, 0.1);
}

View File

@ -83,17 +83,17 @@
outline: 0;
}
&.plyr__tab-focus {
&:focus-visible {
&::-webkit-slider-runnable-track {
@include plyr-tab-focus;
@include plyr-focus-visible;
}
&::-moz-range-track {
@include plyr-tab-focus;
@include plyr-focus-visible;
}
&::-ms-track {
@include plyr-tab-focus;
@include plyr-focus-visible;
}
}
}

View File

@ -42,7 +42,7 @@
// Displaying
.plyr .plyr__control:hover .plyr__tooltip,
.plyr .plyr__control.plyr__tab-focus .plyr__tooltip,
.plyr .plyr__control:focus-visible .plyr__tooltip,
.plyr__tooltip--visible {
opacity: 1;
transform: translate(-50%, 0) scale(1);
@ -82,7 +82,7 @@
.plyr__controls > .plyr__control:first-child + .plyr__control,
.plyr__controls > .plyr__control:last-child {
&:hover .plyr__tooltip,
&.plyr__tab-focus .plyr__tooltip,
&:focus-visible .plyr__tooltip,
.plyr__tooltip--visible {
transform: translate(0, 0) scale(1);
}

View File

@ -4,8 +4,8 @@
// Nicer focus styles
// ---------------------------------------
@mixin plyr-tab-focus($color: $plyr-tab-focus-color) {
outline: $color dotted 3px;
@mixin plyr-focus-visible($color: $plyr-focus-visible-color) {
outline: 2px dashed $color;
outline-offset: 2px;
}

View File

@ -2,4 +2,4 @@
// Cosmetic
// ==========================================================================
$plyr-tab-focus-color: var(--plyr-tab-focus-color, var(--plyr-color-main, $plyr-color-main)) !default;
$plyr-focus-visible-color: var(--plyr-focus-visible-color, var(--plyr-color-main, $plyr-color-main)) !default;

View File

@ -17,7 +17,7 @@
// Control elements
.plyr--audio .plyr__control {
&.plyr__tab-focus,
&:focus-visible,
&:hover,
&[aria-expanded='true'] {
background: $plyr-audio-control-background-hover;

View File

@ -87,8 +87,7 @@ $embed-padding: (math.div(100, 16) * 9);
// Control elements
.plyr--video .plyr__control {
// Hover and tab focus
&.plyr__tab-focus,
&:focus-visible,
&:hover,
&[aria-expanded='true'] {
background: $plyr-video-control-background-hover;