Description: AlpineJS allows you to easily listen for specific key presses (e.g., .enter, .escape) or key combinations (e.g., .ctrl.enter) on input elements or globally on the window. This makes it simple to add keyboard-driven interactions to your web applications.
AlpineJS provides special modifiers for the x-on directive (or its shorthand @) to handle keyboard events. These modifiers can be chained together.
keydown (key is pressed) or keyup (key is released) events and specify the key.
<input @keydown.enter="submitForm">
<div @keyup.escape="closeModal"></div>
Examples:
.enter (for the Enter/Return key).escape (for the Escape key).space (for the Spacebar).arrow-up, .arrow-down, .arrow-left, .arrow-right.tab.delete (for both Delete and Backspace keys).a, .b, .s) or number (e.g., .1).<input @keydown.arrow-up="moveUp" @keydown.arrow-down="moveDown">
.cmd: Alias for the Command key on macOS (event.metaKey)..ctrl: Alias for the Control key (event.ctrlKey)..shift (checks event.shiftKey).alt (checks event.altKey).meta (checks event.metaKey, often the Command key on Mac or Windows key on Windows).control (checks event.ctrlKey).prevent or .window) doesn't strictly matter, but key-specific modifiers usually come after the event type.
<!-- Listen for Ctrl + Enter -->
<textarea @keydown.ctrl.enter="saveContent"></textarea>
<!-- Listen for Shift + S -->
<div @keydown.shift.s="quickSave"></div>
<!-- Listen for Escape globally on the window -->
<div x-data="{ open: true }" @keydown.window.escape="open = false">
Press Escape to hide me (if I'm 'open').
</div>
.prevent Modifier: You can add .prevent to call event.preventDefault() on the triggered event, stopping the browser's default action.
<input @keydown.enter.prevent="customSubmit">
.window Modifier: To listen for keyboard events globally on the `window` object, rather than just the element itself.
<div @keydown.window.escape="handleGlobalEscape"></div>
.document Modifier: Similar to .window, but listens on the `document` object.
keyup vs keydown inappropriately:
keydown fires as soon as the key is pressed down. keyup fires when the key is released.
For actions like submitting a form on "Enter" or triggering a command, keydown usually provides a more responsive feel. Users expect the action to happen when they press the key.
For actions that might involve a key being held down (like continuous character input where you want to act *after* a sequence, though this is less common for single-key modifiers), or if you want to ensure an action happens only once after a key press-and-release cycle, keyup might be more suitable. For most UI interactions like closing modals or submitting forms, keydown is preferred.
.window or .document) firing too often or when not intended:
When you attach a keyboard listener globally (e.g., @keydown.window.escape="closeModal()"), that event listener is active as long as the Alpine component it's defined in exists in the DOM. If you have multiple components or states where such a listener might be active, ensure your handler function (e.g., closeModal()) has logic to determine if it *should* act. For instance, a modal should only close itself if it's currently open. Otherwise, pressing Escape could trigger unintended actions in multiple components or parts of your UI simultaneously.
<div x-data="{ isModalOpen: false }">
<button @click="isModalOpen = true">Open Modal</button>
<div x-show="isModalOpen" @keydown.window.escape="if (isModalOpen) isModalOpen = false">
Modal Content (Press ESC to close if I am open)
</div>
</div>
In the example above, if (isModalOpen) ensures the action only happens if the modal is the intended target.
Many key combinations (e.g., Ctrl+S for Save, Cmd+R for Reload, Ctrl+P for Print, Alt+F4 on Windows) are standard browser or operating system shortcuts. While AlpineJS (with .prevent) can attempt to override some of these, it's often not a good user experience to hijack universally expected behaviors. Users might get confused or frustrated if a common shortcut doesn't work as expected.
If you absolutely need to use such a combination, ensure it's for a critical, in-app function that makes sense in context, and clearly communicate this custom behavior to the user. Generally, try to choose key combinations that are less likely to conflict with standard browser/OS functions.
Focus this area (click here) and try key presses:
Click here, then try 'Space', 'Ctrl+S' (or 'Cmd+S'), 'Alt+ArrowUp'.
Ctrl+S (or Cmd+S on Mac) is often a browser shortcut. We use .prevent to attempt overriding it for this example. Be cautious with this in real applications.