v-btn component stays in focus state after a click. You know about it, and every time the core team told about MD2 guidelines. But for users, this behavior is still counterintuitive.
So I suggest adding a new property that would force the component to give exactly the same behavior as it did in Vuetify 1.5. Buttons and other elements should lose focus state after a click.
I had posted this in the #sponsors Discord channel where I was also given the link to this issue and it was suggested I post my simple (user-level) solution for this, here. It is:
// Register a global custom directive called `v-blur` that prevents focus
Vue.directive('blur', {
inserted: function (el) {
el.onfocus = (ev) => ev.target.blur()
}
});
I've added that to my mainline code just before the new Vue call and that adds a v-blur directive that I can use with the _specific_ buttons I choose to, e.g.:
<v-btn v-blur @click="onClick">
There is a simple example CodePen of this working here: https://codepen.io/appurist/pen/mdbOLYj?editors=1010
I like this _slightly_ better than putting $event.target.blur() in the click handler directly, since for buttons, there's probably already something there in the @click handler so a extra directive keeps it cleaner.
Also, and more importantly, I'm not certain of the order and timing of the code handling the click vs the focus events. In theory, a blur() call in the click handler might run _before_ the rest of the processing of the click (e.g. if it ran on the next tick) and thus it might be undone by the rest of the click processing, depending on the implementations. Putting it in the onfocus seemed safer since it presumably already processed the click and is processing the focus instead when it sends the notification of change. Since that approach is working for others though, it probably doesn't matter. I'd just be a little concerned about future Vue implementation changes possibly affecting it.
Note, this approach should, in theory, be usable on any element that has an onfocus event, not just buttons.
An aside, but somewhat related: this code snippet is derived from the simple example for auto-focus on the Vue website, which looks like:
// Register a global custom directive called `v-focus` that grabs focus when inserted
Vue.directive('focus', {
inserted: function (el) {
el.focus()
}
})
This adds a global custom directive called v-focus that grabs focus when inserted, which is kind of the opposite case, but I see these as a bit of a matched pair.
I know "blur" resulting in v-blur is probably not great, something like autoblur to correspond to autofocus might be better.
@appurist Thank You for for v-blur. Being a novice this was very helpful and opened up a whole new realm of intrigue.
Okay but this looses the focus in general and not after the click right?
Is there a way to only blur after the click as I would still like retain the focus for when users can only use the keyboard?
@jmdos When this component's element is inserted into the DOM, it is installing a new focus handler that when invoked will blur the element, disabling that focus event. Since it is an onfocus event handler, it will be triggered regardless of the cause (mouse or keyboard).
However, the event (ev) is passed to the focus handler, and while we are only using the ev.target, there's probably a field in ev that you can use to distinguish between the cases you which for it to be triggered by, and those you don't. Once you know what the condition is, just call ev.target.blur() conditionally in an if based on the other member of ev.
(Sorry, I'd check and give you the specific answer but I'm quite late for bed. Hope this helps!)
@appurist Thank you for the clarification :)
Would like to know is this fixed with props retain-focus-on-click?
I am asking this question because I seem to have this behaviour on IE11 but not with Chrome/Edge.
If I change <v-btn icon> into <v-btn icon retain-focus-on-click>, I will have this behaviour on all browsers.
In case it is fixed with retain-focus-on-click, would like to know how I can get this work on IE11?
I don't need this feature at all. Just added to global style
.v-btn:not(.v-btn--text):not(.v-btn--outlined):hover:before {
opacity: 0!important;
}
Most helpful comment
I had posted this in the #sponsors Discord channel where I was also given the link to this issue and it was suggested I post my simple (user-level) solution for this, here. It is:
I've added that to my mainline code just before the
new Vuecall and that adds av-blurdirective that I can use with the _specific_ buttons I choose to, e.g.:<v-btn v-blur @click="onClick">There is a simple example CodePen of this working here: https://codepen.io/appurist/pen/mdbOLYj?editors=1010
I like this _slightly_ better than putting
$event.target.blur()in the click handler directly, since for buttons, there's probably already something there in the@clickhandler so a extra directive keeps it cleaner.Also, and more importantly, I'm not certain of the order and timing of the code handling the click vs the focus events. In theory, a
blur()call in the click handler might run _before_ the rest of the processing of the click (e.g. if it ran on the next tick) and thus it might be undone by the rest of the click processing, depending on the implementations. Putting it in theonfocusseemed safer since it presumably already processed the click and is processing the focus instead when it sends the notification of change. Since that approach is working for others though, it probably doesn't matter. I'd just be a little concerned about future Vue implementation changes possibly affecting it.Note, this approach should, in theory, be usable on any element that has an
onfocusevent, not just buttons.An aside, but somewhat related: this code snippet is derived from the simple example for auto-focus on the Vue website, which looks like:
This adds a global custom directive called
v-focusthat grabs focus when inserted, which is kind of the opposite case, but I see these as a bit of a matched pair.I know "blur" resulting in
v-bluris probably not great, something likeautoblurto correspond toautofocusmight be better.