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

Support for Carmack's act on press vs on release option #7497

Open
elieven opened this issue Dec 8, 2024 · 2 comments
Open

Support for Carmack's act on press vs on release option #7497

elieven opened this issue Dec 8, 2024 · 2 comments

Comments

@elieven
Copy link

elieven commented Dec 8, 2024

Provide a general summary of the feature here

Basically some way to act on press as described by John Carmack. Could either be a separate variant of the usePress hook or be some option within it to act this way.

🤔 Expected Behavior?

On pointer devices:

The press would activate on pointer down. Moving the pointer out while still pressed and back in changes nothing. On release the press ends. So isPressed is false initially. On pointer down isPressed is set to true and the onPress event / handler is called. Moving the pointer outside of the button changes nothing. On pointer up regardless of where the pointer is - inside or outside the button - the isPressed is set to false. Depending on your philosophy it might also be fine to make the isPressed prop false on pointer out and true on pointer in but that might communicate the wrong idea as the press should not fire again since this should only act on pointer down.

On touch devices:

For static controls that you want to act on press instead of on release which is the default for touch devices:

Same as above but on touch down. Since the default is to act the same as usePress does now and there are two ways to deal with presses there would have to be some option at least for touch devices but probably pointer devices too to decide if you should act on press on release.

Other controls (default)

Same behavior as the usePress has now.

😯 Current Behavior

Currently there is no way to make a button act on press as described by Carmack with the provided handlers for the usePress hook. Using something like onPressStart would be the closest but it retriggers when dragging out and in again which should not happen.

💁 Possible Solution

Either add some new press hook or add an option to the usePress to act on press vs act on release. Maybe { actOn?: "press" | "release" }. This should change when the various events e.g. pressEnd, pressChange, press are fired and when the isPressed boolean would change. Since there should be a way to control it separately for touch devices e.g. have act on press for all buttons on desktop or whatever and then only some fixed position ones on touch devices be act on press others act on releas maybe something more like { actOn?: "press" | "release" | { touch?: "press" | "release"; pointer?: "press" | "release" } }

🔦 Context

I am trying to make buttons that act on press as described by Carmack i.e. on pointer down, with no press change when dragging out of the button and no retrigger when dragging back in. This I have not been able to do with the provided usePress hook and its methods. I was considering making my own version but then I'd loose the many features and niceties this library and hook provide in terms of consistency and bug fixes across browsers.

💻 Examples

No response

🧢 Your Company/Team

No response

🕷 Tracking Issue

No response

@devongovett
Copy link
Member

Be careful with this, as acting on pointer down is an accessibility failure in many cases. The user needs to be able to cancel their press after starting it, and dragging off of the button is a common way to support that. See https://www.w3.org/WAI/WCAG21/Understanding/pointer-cancellation.html There are some exceptions, but generally most presses should activate on pointer up.

That being said, usePress has a shouldCancelOnPointerExit option, which I think could work here. When true, it will cancel the press when dragging off the button and will not fire onPressStart again when the pointer returns.

@elieven
Copy link
Author

elieven commented Dec 8, 2024

@devongovett Noted on the accessibility point. I think as this is not the default but instead an option you need to make a conscious decision on when and where to use it should not add any problems in this area if it were included. For accessibility one could include undo functionality in the app or not use the on press action in important places or perhaps offer an "are you sure" modal. Basically this as many other things is an option and you choose to use it. As it would not be the default it should not trample anyone's existing interactions.

Thanks for letting me know about that shouldCancelOnPointerExit I did not see it mentioned anywhere on the usePress docs page. Will look into it. Regardless I still think it would be a neat option as it certainly is used in multiple places - if for no other reason then for things like switching tabs or clicking on an option in a radio input and such things that do not cause any problems when clicked on and don't really need to be cancelled but acting on press there makes things feel crazy faster - seriously I've tested myself and there is at least 65ms between down and up events and that's the fastest I've reasonably clicked. Mostly it's around 80 - 100 and up to 120ms. For a component like a tab that might need about that much to render (80ish ms) or so the difference feels lightning fast.

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

No branches or pull requests

2 participants