ten1seven / what-input

A global utility for tracking the current input method (mouse/pointer, keyboard or touch).
https://ten1seven.github.io/what-input
MIT License
1.35k stars 89 forks source link

Manually change whatInput #105

Open jamiek-acl opened 4 years ago

jamiek-acl commented 4 years ago

Great library, thanks for building it!

I have used what-input to remove the styles from buttons when they have focus and the user is using a mouse.

But I have a page with two buttons, and when the user clicks on Button1, I move the focus to Button2. In this case Button2 should have the focus styles to guide the user's eyes. It looks like there used to be a whatInput.setInput('keyboard'); but this no longer exists. To get the functionality I want, when the user clicks on Button1 I am doing:

document.querySelector("html").setAttribute("data-whatinput", "keyboard");

Then later when they click elsewhere on the page I have to set it back (as it seems to get stuck on keyboard):

document.querySelector("html").setAttribute("data-whatinput", whatInput.ask());

Is there a built-in way to handle this?

Thanks!

ten1seven commented 4 years ago

Hi @jamiek-acl, thanks for using What Input! You are correct that I removed the ability to programmatically set the input type in favor of keeping those values as "sources of truth" for what is happening in the browser. The current input type is stored internally as a variable, so changing the data attribute wouldn't trigger the script to "know" that there was a change that needs to be tracked, so it makes sense that you wouldn't see it trip back to mouse.

The API is pretty light-touch and really only registers a change when the input type changes. It does update data-whatelement and data-whatclasses attributes whenever a new element receives focus, but there is no event that fires when this happens that you can hook into.

I'm wondering if there is a non-What Input solution to your problem? I admit I don't understand the full scope of what you've got, but I'm wondering if you could do:

const button1 = document.querySelector('.button1')
const button2 = document.querySelector('.button2')

button1.addEventListener('click', function() {
   button2.classList.add('keyboardfocus')
   button2.focus()
})

button2.addEventListener('blur', function() {
   button2.classList.remove('keyboardfocus')
})

And then in your CSS:

*:focus,
.keyboardfocus {
   /* focus sytles */
}
jamiek-acl commented 4 years ago

Hi @ten1seven. My example was a little contrived; in reality I am making a re-usable Button component and there's any number of ways a consumer could want to programatically give it focus (onClick another button, onLoad, after api returns, after 13 seconds, etc).

I may be able to do something similar to what you suggested, but do need to keep using what-input:

//button.js
...
forceFocus: {
  this.focus();
  this.classList.add('programatically-focused');
}

onBlur: {
  this.classList.remove('programatically-focused');
}
...

and

//button.scss
// when using mouse and not programatically focused, remove focus style
[data-whatinput="mouse"] &:focus &:not('.programatically-focused') {
  ...
}

Something like that. I'll play around. Thanks!