Sercrod supports keyboard actions with @keydown and @keyup.
Keyboard actions are useful when a component needs to react to keys such as
ArrowUp, ArrowDown, Enter, Escape,
or modifier combinations such as Shift + ArrowUp.
In most cases, keyboard shortcuts and movement controls should be handled with
keydown. keyup is also supported, but it is usually used for
release timing, cleanup, or actions that should happen after a key is released.
A normal @keydown action follows the browser's standard keyboard event behavior.
The element must receive the key event directly, or the event must bubble from a focused descendant.
<serc-rod data="{ y: 0 }">
<div tabindex="0" @keydown.arrowup="y=y-1" @keydown.arrowdown="y=y+1">
<p>Focus this area, then press ArrowUp or ArrowDown.</p>
<p>Y: %y%</p>
</div>
</serc-rod>
In this example, the div is focusable because it has tabindex="0".
Without focus, a normal local keydown event will not be fired on that element.
This is ordinary DOM behavior. Sercrod does not make non-focusable elements focusable automatically.
For application-level keyboard controls, Sercrod also supports the .window modifier.
<serc-rod data="{ y: 0 }">
<div @keydown.window.arrowup="y=y-1" @keydown.window.arrowdown="y=y+1">
<p>Press ArrowUp or ArrowDown anywhere in the window.</p>
<p>Y: %y%</p>
</div>
</serc-rod>
When .window is used, the element is not the actual keyboard event target.
Instead, the attribute is treated as a declaration.
The key event is observed on window. The action is executed in the nearest
<serc-rod> context, and only that host is updated.
This means that .window lets HTML describe a keyboard shortcut without hiding
the logic in a separate JavaScript function.
@keydown.window.arrowup="y=y-1"
This reads as: when the window receives ArrowUp, decrease y
in this Sercrod host.
You may place several window key declarations on one ordinary element.
<serc-rod data="{ x: 0, y: 0 }">
<div
@keydown.window.arrowleft="x=x+1"
@keydown.window.arrowright="x=x-1"
@keydown.window.arrowup="y=y-1"
@keydown.window.arrowdown="y=y+1">
</div>
<p>X: %x%</p>
<p>Y: %y%</p>
</serc-rod>
This style is useful when you want to keep the keyboard map in one place.
The div does not need to be focusable in this example, because the declarations
use .window.
You may also split the declarations across multiple ordinary elements.
For example, input type="hidden" can be used as an invisible declaration location.
<serc-rod data="{ x: 0, y: 0 }">
<input type="hidden" @keydown.window.arrowleft="x=x+1">
<input type="hidden" @keydown.window.arrowright="x=x-1">
<input type="hidden" @keydown.window.arrowup="y=y-1">
<input type="hidden" @keydown.window.arrowdown="y=y+1">
<p>X: %x%</p>
<p>Y: %y%</p>
</serc-rod>
In this example, the hidden inputs do not receive keyboard focus. They are only used as declaration locations.
Because .window is present, keyboard events are observed on window.
The actions still run in the nearest <serc-rod> context.
Both styles are valid. You can group several declarations on one element, or split them across multiple hidden inputs or ordinary elements.
The difference is mainly readability and placement. If declarations are placed inside a nested
<serc-rod>, the nearest host changes, and the action belongs to that nested host.
Keyboard key names are matched case-insensitively.
The recommended Sercrod style is lowercase.
@keydown.arrowup="y=y-1"
@keydown.enter="submitted=true"
@keydown.escape="open=false"
Official KeyboardEvent.key names are also accepted.
For example, these refer to the same key:
ArrowUp
arrowup
ARROWUP
arrowUp
The official browser key name is ArrowUp, but Sercrod examples use
arrowup because lowercase names are easier to read in HTML attributes.
Modifier keys can be combined with +. The order does not matter.
<serc-rod data="{ y: 0 }">
<div
@keydown.arrowup+shift="y=y-10"
@keydown.shift+arrowdown="y=y+10">
<p>Y: %y%</p>
</div>
</serc-rod>
These two forms are equivalent:
@keydown.arrowup+shift="y=y-10"
@keydown.shift+arrowup="y=y-10"
Supported modifier keys include:
shift
ctrl
alt
meta
Examples:
@keydown.s+ctrl="saved=true"
@keydown.enter+ctrl="submitted=true"
@keydown.enter+ctrl+shift="submitted=true"
Sercrod does not treat arbitrary non-modifier combinations such as a+b
as a normal shortcut condition in the initial keyboard specification.
@keydown.a+b="value=value+1"
This should produce [Sercrod warn].
The reason is that true arbitrary multi-key detection requires pressed-key state management.
Modifier combinations such as arrowup+shift, s+ctrl,
and enter+ctrl+shift are supported.
Use .prevent to call preventDefault() when the key condition matches.
<serc-rod data="{ y: 0 }">
<div @keydown.window.arrowup.prevent="y=y-1">
<p>Y: %y%</p>
</div>
</serc-rod>
.preventDefault is also accepted.
@keydown.window.arrowup.preventDefault="y=y-1"
The recommended form is .prevent.
preventDefault() is applied only when the key condition matches.
For example, @keydown.window.arrowup.prevent prevents the default behavior
for ArrowUp, not for every key.
When .window.prevent is used, the matching key's default browser behavior
is prevented at the window level.
This can also suppress page scrolling or the normal key behavior of focused form controls.
Use it only when the keyboard action is intended to take over that key.
keyup uses the same key and modifier syntax.
@keyup.escape="open=false"
@keyup.window.arrowup="released=true"
However, shortcuts and movement controls are usually handled with keydown.
Use keyup when the action should happen when a key is released.
Be careful with modifier conditions on keyup.
@keyup.arrowup+shift="selected=true"
This matches only if Shift is still pressed when ArrowUp is released.
If Shift is released first, the condition may not match.
Window key declarations are tied to the nearest <serc-rod> host.
When that host is removed from the DOM, Sercrod cleans up its window key registrations using the Custom Element lifecycle.
This prevents removed components from continuing to react to window keyboard events.
.window is powerful and should be used intentionally.
If multiple <serc-rod> hosts declare the same window shortcut,
each matching host may react.
Sercrod does not automatically decide which host is active.
Use local key events when the shortcut should belong to a focused area.
Use .window when the shortcut should work at the window level.