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

Prevent hotkeys used when our dialog is open - take 2 #10

Closed

Conversation

PhilETaylor
Copy link
Contributor

Different approach here, using the event data to determine if we are in the dialog and allowing the arrows and tab (shift tab also works as does escape)

Copy link

vercel bot commented Dec 2, 2023

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
cmd-dialog ✅ Ready (Inspect) Visit Preview 💬 Add feedback Dec 2, 2023 6:58pm

typescript-eslint/prefer-nullish-coalescing
@OzzyCzech
Copy link
Owner

Thanks, but this approach also block other user defined shortcuts (e.g. Cmd+E for email and so on) I will try figure out, how to solve this, maybe callback for hotkeys.filter function where you can block only specific shortcuts 🤷‍♂️

@OzzyCzech
Copy link
Owner

Hi @PhilETaylor there is simple way how to solve this problem without corrupt cmd-dialog functionality

import hotkeys from 'hotkeys-js';

hotkeys.filter = (event) => {
  return event.target.tagName === 'CMD-DIALOG' ? event.key !== 'a' : true;
};

you can import hotkeys from source and then handle you a shortcut code. This is only way how to solve it clearly. I can't handle your case as something that's common.

@OzzyCzech OzzyCzech closed this Dec 4, 2023
@PhilETaylor
Copy link
Contributor Author

I don't think what Im doing is uncommon - Im just having single char hotkeys like s or a

When pressing s or a in the input box of the dialog, hotkeys should be intelligent enough to not trigger - this is a bug in hotkeys not your code, and would best be reported and fixed in hotkeys (but Im guessing they will say they cannot support Lit Elements)

I personally believe that no hotkey should trigger while the dialog is shown (this is what github does) - but thats personal choice, you would be having the same issue as me if your demo site did not use the command prefix on the keyboard shortcuts - unfortunately I have almost a decade of muscle memory and 1000s of paying clients using single digit keyboard shortcuts (like Github uses) and so cannot change all these to be prefixed with a command or modifer.

Im happy to revert my changes to your code as they are currently broken as you explain - and adding the second approach directly in my own JS code seems to work perfectly for my own needs and architectural decision above.

@OzzyCzech
Copy link
Owner

According to my research there are both approaches, some cmd dialogs block hotkeys some not

https://github.com/OzzyCzech/cmd-dialog/releases/tag/v1.5.0

@PhilETaylor
Copy link
Contributor Author

What your project and Ninja Keys have in common is your examples use modifiers (such as CMD + h) whereas single char keyboard hot keys such as s is my test. S would take me to the list of sites in my app.

The "problem" is that is I type "bugs" in the input box of the web component (Lit) then on pressing the s in bugs Im redirected to the Sites page, instead of just filtering the actions by the word bugs - ultimately that I see as a bug in HotKeys because it doesnt "see" the input box in a web component (Lit element) as an inputbox.

I was playing this afternoon and remembered why I moved from HotKeys to Mousetrap some years ago - and it was sequential keys (Pressing g and then i for example) - Hotkeys doesnt support that, Mousetrap does

There are many issues open in the Hotkeys repo requesting sequential keystroke support but like most of the keyboard navigation repos, they all seem abandoned with little action and little movement forward since release. :(

As my app already has sequential keystrokes, as well as an old cmd+k dialog I think Im going to need to fork this project - but thats on the back burner now as I have other code to write first so will come back to this (sorry traveling this week so away from desk)

Appreciate your hard work on this - this project alone has taught me about Lit and ts to JS compiling so its been very very worthwhile for this PHP developer :)

@OzzyCzech
Copy link
Owner

I am decide to switch from HotKeys to tinykeys

There are some BC breaks but now you can use single letter inside dialog. Check latest version from master.

@PhilETaylor
Copy link
Contributor Author

but now you can use single letter inside dialog

Doesnt seem to work like that - I still get navigated when pressing s in my app and when using https://cmd-dialog-git-main-ozzyczech.vercel.app/ if you type abc/ you get navigated away when pressing /

Sorry :)

@PhilETaylor
Copy link
Contributor Author

PhilETaylor commented Dec 6, 2023

What IS now working is a shortcut containing more than one key s s s for example now works on the pressing of the third s :) thats progress in one area :) but unfortunatly pressing sss in the input box also triggers on the third press and navigates away :(

@OzzyCzech
Copy link
Owner

but now you can use single letter inside dialog

Doesnt seem to work like that - I still get navigated when pressing s in my app and when using https://cmd-dialog-git-main-ozzyczech.vercel.app/ if you type abc/ you get navigated away when pressing /

Sorry :)

Sorry I forgot event.preventDefault() there https://github.com/OzzyCzech/cmd-dialog/blob/main/index.html#L81

@OzzyCzech
Copy link
Owner

What IS now working is a shortcut containing more than one key s s s for example now works on the pressing of the third s :) thats progress in one area :) but unfortunatly pressing sss in the input box also triggers on the third press and navigates away :(

This is how tinykey works (check jamiebuilds/tinykeys#17)
You have to handle it with your code, this is why event is now sent to the onAction function

@PhilETaylor
Copy link
Contributor Author

You have to handle it with your code, this is why event is now sent to the onAction

Hmmm so now I have to write custom handlers for each key stroke to check if its been made in a INPUT box or not?

@OzzyCzech
Copy link
Owner

OzzyCzech commented Dec 6, 2023

Can be handled with single line of code:

if (!/TEXTAREA|INPUT|CMD-DIALOG/.test(event.target.tagName)) {
  // ... do action
} else {
  // .. do nothing
}

I can't cover all possibilities.

@PhilETaylor
Copy link
Contributor Author

PhilETaylor commented Dec 6, 2023

ok for me I have added

if (event instanceof KeyboardEvent && event.key !== 'Enter' && this.dialog.open){
  return;
}

in the _triggerAction method and this is enough to give me a near perfect app. It handles s when closed, it doesnt handle s when typed in the input box, but it also allows the arrows to find the Sites option and when enter is pressed on that action item the action is correctly run. This is perfect. just means I need to compile each release with this but thats fine - unless you want to test and see if you want to do this too. Up to you, but I can sleep happy tonight - progress :)

@OzzyCzech
Copy link
Owner

I just added a custom cancellable event to the _triggerAction function, you can decide whether to execute the action or not.

const dialog = document.querySelector('cmd-dialog');

dialog.addEventListener('action', (event) => {
  if (
    dialog.isOpen &&
    event.detail.parentEvent instanceof KeyboardEvent &&
    event.detail.parentEvent.key !== 'Enter'
  ) {
    event.preventDefault(); // do not perform action
  }
});

@PhilETaylor
Copy link
Contributor Author

Thanks - im going to have to come back to all this, I just realised that if I have an action for Sites with s as the trigger in the cmd-dialog, when I type s in my contact form textarea on the page - without the cmd-dialog showing, the action is being triggered :-( ... Im exhausted from travelling and working this week in hotels, Im going to have to come back to this next week.

@PhilETaylor
Copy link
Contributor Author

bookmarking jamiebuilds/tinykeys#17 :-(

@PhilETaylor
Copy link
Contributor Author

PhilETaylor commented Dec 7, 2023

This is perfect!

dialog.addEventListener('action', (event) => {
    if (
      dialog.isOpen &&
      event.detail.parentEvent instanceof KeyboardEvent &&
      event.detail.parentEvent.key !== 'Enter'
    ) {
      event.preventDefault(); // do not perform action
    }

    if (!dialog.isOpen && ['INPUT', 'TEXTAREA'].includes(event.detail.parentEvent.target.tagName)){
      event.preventDefault();
    }
  });

THANKS!

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

Successfully merging this pull request may close these issues.

2 participants