📦 Installation

NPM
npm install @mbolli/datastar-attribute-on-keys
Setup
<script type="importmap">
{
  "imports": {
    "datastar": "https://cdn.jsdelivr.net/gh/starfederation/datastar@v1.0.0-RC.6/bundles/datastar.js"
  }
}
</script>
<script type="module" src="https://cdn.jsdelivr.net/npm/@mbolli/datastar-attribute-on-keys@1/dist/index.js"></script>

📊 Live State

Signals

        

🎹 Datastar On-Keys Plugin

Interactive demo showcasing keyboard event binding with key combinations and multiple keys

📖 Usage Guide

The data-on-keys attribute allows you to bind keyboard events to Datastar actions with powerful key combinations and modifiers.

Basic Syntax

data-on-keys[:key-spec][__modifier1][__modifier2]="action"

Key Specifications

The key-spec defines which keys trigger the action. It can be:

  • Single keys: space, enter, escape, tab, f1, a
  • Key combinations: ctrl-k, alt-enter, shift-space, meta-s, ctrl-shift-z
  • Multiple options: enter.tab, escape.f1.ctrl-q (any of these will trigger)
  • Any key: omit the key-spec entirely to capture all key presses

Key Name Mapping

Common key aliases are automatically mapped to standard JavaScript key names:

Special Keys

  • space → Space character
  • enter / return → Enter
  • escape / esc → Escape
  • tab → Tab
  • backspace → Backspace
  • delete / del → Delete

Navigation Keys

  • up → ArrowUp
  • down → ArrowDown
  • left → ArrowLeft
  • right → ArrowRight
  • pageup → PageUp
  • pagedown → PageDown

Note: Function keys (f1-f12), letter keys (a-z), and other standard keys work as expected.

Target Modifiers

  • Default (no modifier) - Binds to window (global)
  • __el - Binds to the element itself (requires focus)

Behavior Modifiers

  • Default - Prevents default browser behavior (preventDefault())
  • __noprevent - Allows default browser behavior
  • __stop - Stops event propagation (stopPropagation())

Event Timing

  • Default - Triggers on keydown
  • __up - Triggers on keyup

Event Listener Options

  • __capture - Use capture phase
  • __passive - Passive event listener
  • __once - Remove listener after first trigger

Common Examples

<!-- Global shortcuts -->
<div data-on-keys:ctrl-s="saveDocument()"></div>
<div data-on-keys:escape="closeModal()"></div>

<!-- Element-specific -->
<input data-on-keys:enter__el="submitForm()">
<textarea data-on-keys:ctrl-enter__el="submit()"></textarea>

<!-- Allow default behavior -->
<div data-on-keys:tab__noprevent="logTab()"></div>

<!-- Multiple triggers -->
<div data-on-keys:escape.f1.ctrl-h="showHelp()"></div>

Test 1: Single Key - Space Counter

Uses data-on-keys:space to increment counter on spacebar (prevents page scroll by default).

Press Space to increment counter:

Test 2: Key Combination - Ctrl+K

Uses data-on-keys:ctrl-k for a global keyboard shortcut (window is now default).

Press Ctrl + K anywhere to toggle mode:

Mode:

Test 3: Multiple Keys - Enter or Tab

Uses data-on-keys:enter.tab to trigger on multiple keys.

Press Enter or Tab to show message:

Test 4: Global Events - Modal Control

Uses data-on-keys:f1 to open modal and data-on-keys:escape to close it (window is now default).

Press F1 anywhere to open modal, Escape to close it:

🎹 Keyboard-Controlled Modal

This modal was opened with F1 and can be closed with Escape or by clicking the button below.

Test 5: Global Key Monitor

Uses data-on-keys to capture any key press globally (prevents default to avoid conflicts).

Last key pressed:

Press any key anywhere on the page to see it captured:

Test 6: Element-Specific Key Binding

Uses data-on-keys:ctrl-enter__el to capture Ctrl+Enter key only when the input has focus.

Focus this input and press Ctrl + Enter (only works when input is focused):

Test 7: Allow Default Behavior

Uses data-on-keys:tab__noprevent to capture Tab key but still allow normal tab navigation.

Tab through these inputs - the counter will increment but tab navigation still works:

Test 8: Keyup Events

Uses data-on-keys:space__up to trigger on key release instead of key press.

Keydown Events
Keyup Events

Press and hold Space, then release to see the difference between keydown and keyup:

Tip: Hold space to see keydown fire repeatedly, then release to see keyup fire once.