A Datastar plugin that provides keyboard event binding with support for key combinations and multiple keys.
Datastar is a hypermedia-focused framework that brings reactive signals and declarative DOM manipulation to your HTML. While it includes great event handling, this plugin extends keyboard event capabilities to support:
- Key combinations (e.g.,
Alt-Q,Ctrl-Shift-S) - Multiple key bindings (e.g.,
Escape.Enterto trigger on either key)
npm install @mbolli/datastar-attribute-on-keysThis plugin requires an import map to resolve the datastar module. Set up your HTML like this:
<script type="importmap">
{
"imports": {
"datastar": "https://cdn.jsdelivr.net/gh/starfederation/datastar@v1.0.0-RC.6/bundles/datastar.js"
}
}
</script>
<script type="module">
// Import the plugin - it will auto-register with datastar
import 'https://cdn.jsdelivr.net/npm/@mbolli/datastar-attribute-on-keys@1/dist/index.js';
</script>Note: Using @1 will automatically use the latest v1.x.x version.
This plugin adds an on-keys attribute to Datastar that allows you to bind keyboard events to reactive actions.
<div data-on-keys:escape="$modal.close()">
<!-- Triggers when Escape key is pressed -->
</div><div data-on-keys:alt-q="$app.quit()">
<!-- Triggers when Alt+Q is pressed -->
</div>
<div data-on-keys:ctrl-shift-s="$document.save()">
<!-- Triggers when Ctrl+Shift+S is pressed -->
</div><div data-on-keys:escape.enter="$dialog.close()">
<!-- Triggers when either Escape OR Enter is pressed -->
</div>
<div data-on-keys:space.enter.alt-q="$action.execute()">
<!-- Triggers on Space, Enter, or Alt+Q -->
</div>By default, key events are listened for globally on the window:
<div data-on-keys:escape="$modal.close()">
<!-- Listens for Escape key globally -->
</div>Use the el modifier to listen only when the element has focus:
<input data-on-keys:enter__el="$form.submit()"><!-- Only triggers when this input is focused -->The plugin supports several modifiers:
el- Listen on the element instead of window (requires focus)noprevent- Allow default browser behavior (default prevents)stop- CallstopPropagation()on the eventup- Listen forkeyupinstead ofkeydown(default)capture- Use capture phasepassive- Use passive event listeneronce- Only trigger once
<div data-on-keys:tab__noprevent="$counter++">
<!-- Count tab presses but still allow tab navigation -->
</div>Control when and how often callbacks are executed:
delay.{time}- Postpone execution (e.g.,__delay.500ms,__delay.1s)debounce.{time}- Wait for user to stop before executing (supports__leading,__notrailing)throttle.{time}- Limit execution rate (supports__trailing,__noleading)
<div data-on-keys:enter__delay.500ms="$message = 'Delayed!'"></div>
<input data-on-keys__debounce.300ms__el="$search($event.target.value)">
<div data-on-keys:space__throttle.1s="$counter++"></div>viewtransition- Wrap state changes in the View Transitions API for smooth animations
<div data-on-keys:space__viewtransition="$counter++">
<!-- Counter updates with smooth animation -->
</div>Common key aliases are automatically mapped to standard JavaScript key names:
Special Keys:
space→ Space characterenter/return→ Enterescape/esc→ Escapetab→ Tabbackspace→ Backspacedelete/del→ Delete
Navigation Keys:
up→ ArrowUpdown→ ArrowDownleft→ ArrowLeftright→ ArrowRightpageup→ PageUppagedown→ PageDown
Other Keys:
- Letters:
a,b,c, etc. - Numbers:
1,2,3, etc. - Function keys:
f1,f2, etc. → F1, F2, etc. - Modifiers:
ctrl/control,alt,shift,meta/cmd/command
<div class="modal" data-on-keys:escape="$modal.close()">
<!-- Modal content -->
</div><div data-on-keys:space="$counter++">
Count: <span data-text="$counter"></span>
</div><div data-on-keys:ctrl-s="$document.save()">
<!-- Ctrl+S to save - global and prevents browser save dialog -->
</div>
<div data-on-keys:ctrl-z="$document.undo()">
<!-- Ctrl+Z to undo - global and prevents browser undo -->
</div>Run the automated tests:
pnpm testOr open index.html locally in a browser to interactively test the plugin with Datastar.
This project uses automated releases via GitHub Actions. When you push to main:
- Tests run automatically - Build and tests must pass
- Version bumping - Add to your commit message:
[major]for breaking changes (1.0.0 → 2.0.0)[minor]for new features (1.0.0 → 1.1.0)- Default: patch for bug fixes (1.0.0 → 1.0.1)
- Automatic publishing - Package is published to npm
- GitHub Release created - With auto-generated release notes
MIT