Disable/Enable Hotkeys
We are now able to register our hotkeys, scope them to the component (or part of a component) and prevent stale state inside our callback. But our hotkeys are always active. If the component has received focus, it will always trigger. However, sometimes we want to dynamically decide if the hotkey should even be enabled.
There are multiple ways to disable a hotkey. Let's go through all of them.
Dynamically disable or enable
Toggle hotkeys with the enabled
flag
Using the enabled
flag in the options object, we can dynamically tell useHotkeys
if the hotkey should be active or not.
This is useful to programmatically decide (depending on some internal state of our app or user input) if the hotkey
should be active or not. enabled
takes a Trigger
type, so it can either be a boolean or a function that returns a boolean.
See the documentation for the enabled option for more information.
If we use the returned ref
of the callback to scope our hotkey to a specific sub-tree of our component, note that
this will automatically activate or deactivate our hotkey depending on which part of the page has active focus.
Prevent default browser behavior
Some hotkeys like meta + s
are already assigned to a browser function, in this case saving a website to
the users local disk. Sometimes we want to override these hotkeys to implement our own functionality. Maybe we want to
build a text editor or some other user based creation tool that needs a save shortcut to save the current progress. It
would be silly to introduce a new shortcut for saving the users progress, since every user knows that meta + s
is the
universal shortcut for saving.
To prevent the default browser behavior, we can just set preventDefault
to true in our options:
Please be aware that there are some hotkeys that we cannot override, because they would interfere with a safe browsing
experience for the user. These depend on the browser.
For example in Chrome, most notably those are meta + w
which closes a tab, meta + n
for opening a new window and meta + t
to open a new tab.
Additionally meta + shift + w
(closing all tabs of the current window), meta + shift + n
(opening incognito window) and
meta + shift + t
(reopen the last closed tab) cannot be overridden.
meta + up + 1..9
on the other hand focuses the corresponding tab of the active window and also cannot be overridden.
Disable callback execution
In the first section we set enabled
to false
to disable our hotkey. Internally this will also unbind our event listeners
from the DOM. To keep the event listeners but not execute the callback, we can give enabled
a function that returns false
.
We can combine both the enabled
and preventDefault
options.
function ExampleComponent() {
useHotkeys('meta+s', () => alert('We saved your progress!'), {
enabled: () => false,
preventDefault: true,
})
return (
<div>
<p>Press cmd+s (or ctrl+s for non mac) to open custom save dialog.</p>
</div>
)
}
This might be preferred if we want to build a custom hook on top of useHotkeys
that always prevents the default behavior.
If enabled
is set to false
the internal browser event will not trigger at all, therefore no browser behavior will happen.
If we set enabled
to () => false
our callback still won't get executed, but the event will trigger and therefore potential
browser behavior will happen.
Enable hotkeys on form fields
By default, hotkeys won't trigger when the user is focusing a form field. This is the expected case most of the time.
For example, if we'd listen for the hotkey 'p'
on a review page for apps and a user would try to type This app is simply
the best
into the review input field, the resulting text would be This a is simly
the best
. Same with keystrokes that start with shift + ...
since this normally capitalizes a letter.
So it is good, that useHotkeys
is smart enough to back off during focused form fields. However, sometimes you still
want hotkeys to be enabled even when the user is focusing on an input field. There might be again the need so save
the users progress. Our previous example would not trigger if the user is focusing a form field. Instead, we have to
enable the hotkey on certain form fields. We can use the enableOnFormTags
option for that which takes an array of form tags:
function ExampleComponent() {
useHotkeys('meta+s', (e) => {
e.preventDefault()
alert('We saved your progress!')
// ... set up our own saving dialog.
}, {
enableOnFormTags: ['input', 'select', 'textarea']
})
return (
<div>
<p>Press cmd+s (or ctrl+s for non mac) to open custom save dialog.</p>
</div>
)
}
We tell useHotkeys
that the given keystrokes should be listened to and the callback executed even when the user is currently
focusing an input, select or textarea field. To enable the hotkey on any input tag, set the enableOnFormTags
option to true
.
Enable hotkeys on tags leveraging contentEditable
The contentEditable
attribute
allows users to edit text even though it is not part of an input field. For example a <div>
tag could have the
contentEditable
attribute. Sometimes we want hotkeys to still trigger, even though a user is focusing an editing a
tags content. A good example for this might be the editor on medium.com. useHotkeys
provides
an option for that: