I'm was trying to make keyboard navigation focus outline for accessibility. The pseudo :focus-visible class works fine on all elements except input, like text or textarea. It seems input will always have this pseudo class active, since it requires keyboard input. Looking around I couldn't find a way to to fix it, so it would behave like all other interactable elements. So I thought I'd just sort it through onFocus while rendering, by showing/hiding custom css class that will appear and disappear depending on how user focused the input.
I've managed to do as much, but the problem is I don't know how I can now further differentiate where the input is coming from, keyboard or mouse. Here's what I got so far. First react hooks:
const [keyboardFocus, setKeyboardFocus] = useState(false);
const toggleKeyboardFocusOn = () => setKeyboardFocus(true);
const toggleKeyboardFocusOff = () => setKeyboardFocus(false);
So we have they keyboardFocus hook, and toggles for onFocus and onBlur which should define weather input should have keyboard focus or not. Then I have the class selector to determine weather the keyboard only outline is active or not:
const inputClassNames = classNames({
...
[css.keyboardOnlyFocus]: keyboardFocus,
});
And finally in rendering of input I have
onBlur={toggleKeyboardFocusOff}
onFocus={toggleKeyboardFocusOn}
So far, focusing in and out works, an will display the outline. What I'm having trouble is understanding how can I now in onFocus determine if the event came from mouse, in which case it should be ignored or if it came from keyboard.
One of the solutions I tried was something like this:
onFocus={(e) => ({
if(e.key === 'Tab') {
toggleKeyboardFocusOn;
}
})
However nothing was happening, and console output of e.key showed as undefined. So what would be the correct way to tell onFocus that the event is coming from mouse or keyboard?