Created this issue to keep track of what was discussed in #224
Self-assigned to @kevjin
We can conditionally enable focus outline if keyboard navigation is being used. May be a good middle-ground. Something like:
const TAB_KEYCODE = 9;
const FOCUS_ATTR = 'data-is-focused';
const BLUR_EVENT = 'blur';
const FOCUS_EVENT = 'focus';
const KEYDOWN_EVENT = 'keydown';
const MOUSEDOWN_EVENT = 'mousedown';
let IS_MOUSE_EVENT = false;
/**
* Attaches listeners for keydown, mousedown, focus, and blur to the document,
* which handle adding or removing focus outline css class for mouse events.
*/
export function start() {
const docEl = window.document.documentElement;
IS_MOUSE_EVENT = false;
if (!docEl) {
throw new Error('Please init before running install().');
}
docEl.addEventListener(KEYDOWN_EVENT, handleKeyDown, false);
docEl.addEventListener(MOUSEDOWN_EVENT, handleMouseDown, false);
docEl.addEventListener(FOCUS_EVENT, handleFocus, true);
docEl.addEventListener(BLUR_EVENT, handleBlur, true);
}
/**
* Detaches listeners
*/
export function stop() {
const docEl = window.document.documentElement;
if (docEl) {
docEl.removeEventListener(KEYDOWN_EVENT, handleKeyDown, false);
docEl.removeEventListener(MOUSEDOWN_EVENT, handleMouseDown, false);
docEl.removeEventListener(FOCUS_EVENT, handleFocus, true);
docEl.removeEventListener(BLUR_EVENT, handleBlur, true);
}
}
function handleKeyDown(event) {
if (event.keyCode === TAB_KEYCODE) {
IS_MOUSE_EVENT = false;
}
}
function handleMouseDown(event) {
IS_MOUSE_EVENT = true;
}
function handleFocus(event) {
if (IS_MOUSE_EVENT && event.target !== event.currentTarget) {
event.target.setAttribute(FOCUS_ATTR, true);
}
}
function handleBlur(event) {
if (event.target !== event.currentTarget) {
event.target.removeAttribute(FOCUS_ATTR);
}
}
With the CSS:
[data-is-focused="true"] {
outline: none;
}
Most helpful comment
We can conditionally enable focus outline if keyboard navigation is being used. May be a good middle-ground. Something like:
With the CSS: