Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature Request] A property for remove focus state on v-btn and other components #8572

Closed
sentbyravens opened this issue Aug 16, 2019 · 14 comments
Assignees
Labels
T: feature A new feature
Milestone

Comments

@sentbyravens
Copy link

sentbyravens commented Aug 16, 2019

Problem to solve

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.

Proposed solution

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.

@ghost ghost added the S: triage label Aug 16, 2019
@sentbyravens sentbyravens changed the title [Feature Request] v-btn component stays in focus state after click [Feature Request] A directive for remove focus state on v-btn and other components Aug 16, 2019
@sentbyravens sentbyravens changed the title [Feature Request] A directive for remove focus state on v-btn and other components [Feature Request] A property for remove focus state on v-btn and other components Aug 16, 2019
@nekosaur nekosaur added T: feature A new feature and removed S: triage labels Aug 16, 2019
@appurist
Copy link
Contributor

appurist commented Aug 23, 2019

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.

@jrmore
Copy link

jrmore commented Dec 6, 2019

@appurist Thank You for for v-blur. Being a novice this was very helpful and opened up a whole new realm of intrigue.

@jmdos
Copy link

jmdos commented Jan 7, 2020

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?

@appurist
Copy link
Contributor

appurist commented Jan 8, 2020

@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!)

@jmdos
Copy link

jmdos commented Jan 9, 2020

@appurist Thank you for the clarification :)

@billpchie
Copy link

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?

@yoldar
Copy link

yoldar commented Apr 10, 2020

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;
}

@TaeyoonKwon
Copy link

You don't have to do all that. Just add this to global style and everything solves.

Media query is needed because if not, it will remove hover effects on Desktop view.

@media screen and (max-device-width: 768px) { .v-btn:hover:before { opacity: 0 !important; } }

@appurist
Copy link
Contributor

appurist commented Jan 1, 2021

@yoldar and @TaeyoonKwon : How is that going to help to remove the actual focus? (The issue reported is not one of opacity or CSS styles at all.)

@TaeyoonKwon
Copy link

@yoldar and @TaeyoonKwon : How is that going to help to remove the actual focus? (The issue reported is not one of opacity or CSS styles at all.)

Whether it is technically focused or not isn't important. As he said, the behavior that button is still focused even after touch event is over is counterintuitive to UX. And it can be solved with simple css.

@appurist
Copy link
Contributor

appurist commented Jan 2, 2021

@TaeyoonKwon "Whether it is technically focused or not isn't important."

That's the entire point of this Issue. That you try to solve a different problem is not relevant here. Again, the issue is not one of styling but focus.

Edit to add: I think I am starting to understand this point, given my observations below, where the focus actually remains, but the focus is just not observable without the keyboard. It is important for the next/sequence to remain in place while just not highlighting the button in any way after release.

@appurist
Copy link
Contributor

appurist commented Jan 2, 2021

However, the problem may be moot as it seems buttons don't seem to hold the focus after mouse click anymore. The buttons do hold the focus if you tab through, but that actually seems like a desirable accessibility/keyboard support behavior; it was really the "holding focus after click" that was disruptive, and that seems to be gone now.

I suspect the focus/tabbing work that was done for 2.3.0 has rationalized this behavior to only be relevant for when Tab was used to focus a button. I prefer this behavior so even though I don't want a button (mouse) click to hold the focus, I think my v-blur directive is no longer desirable; the default Vuetify behavior now is complete (and better).

From my perspective, this issue can be closed, but I am not the original reporter, I just agreed with the request and provided a brute-force workaround, which is not as good as the Vuetify behavior is by default now.

@jmdos I'm not sure if this changed or if it's been like this all along but the concept of which element has the focus is in fact retained (even with the v-blur directive) so keyboard tabbing still continues from the one that was blurred. It seems the current behavior is much improved and very slick. Try it with my codepen here, and bear in mind that I prefer the default handling now rather than that of the middle button behavior (i.e. my opinion is we don't need v-blur anymore and can close this issue.)

@PepiBobanov
Copy link

PepiBobanov commented May 14, 2021

@appurist : Thanks for your solution. Without it, the following code always leave tooltip active, after dialog is closed

`

<template v-slot:activator="{ on:dialog, attrs }">
  <v-tooltip bottom>
    <template v-slot:activator="{ on:tooltip }">
      <v-btn
        fab
        dark
        small
        color="primary"
        v-bind="attrs"
        v-on="{ ...tooltip, ...dialog }"
        v-blur
      >
        <v-icon>mdi-account-plus</v-icon>
      </v-btn>
    </template>
    <span>Tooltip</span>
  </v-tooltip>
</template>

...
`

@hrobertson
Copy link
Contributor

hrobertson commented Jun 16, 2021

I found that if you don't use the v-dialog activator slot it doesn't have the problem.
You can see this in the docs: https://vuetifyjs.com/en/components/dialogs/#without-activator
The button does not remain focused after the dialog is closed.

Note this only works with a v-btn. I initially just had a v-icon with an @click="dialog=true" but the icon remained focused.

Directly related: #7907

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
T: feature A new feature
Projects
None yet
Development

No branches or pull requests