sercrod

Keyboard events

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.

Local key events

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.

Window key events

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.

Declaring multiple window keys on one element

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.

Declaring window keys with hidden inputs

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.

Key names

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

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"

Multiple non-modifier keys

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.

Preventing default browser behavior

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.

About keyup

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 cleanup

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.

Notes

.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.