Vize

on-start-typing

Whether a keyboard event would type a printable character.

Package @vizejs/composable/on-start-typing
Own the source vize lib pull composable:on-start-typing
Runtime exports isTypingKeystroke, onStartTyping
Gzip budget 1536 B

Minimal setup

Use a Vue 3.5+ project with Vue SFC compilation configured (see Vite+ integration).

vp install @vizejs/composable

Import the entry directly. Call lifecycle-bound utilities inside <script setup> so cleanup follows the component scope; consult the runtime contract for this entry's SSR and hydration behavior.

import { isTypingKeystroke, onStartTyping } from "@vizejs/composable/on-start-typing";

Try it

Focus local guide search when typing begins

Redirect a printable key from a non-editable reading control into search while respecting native field editing and existing modifier shortcuts.

Open the interactive example

What to observe: Focus Reading control and press a letter: search receives actual focus and the shortcut delivery count increments. Then type to filter the local guides. Space activates the reading button normally, navigation keys do not redirect, and Ctrl/Meta/Alt shortcuts are ignored. Editing Workshop note does not focus search. Stop typing shortcut removes the redirect while both fields remain usable.

The default host is this preview's document. onStartTyping matches single printable characters other than space, with no Ctrl/Meta/Alt modifier and no editable element focused. The handler only counts and focuses the actual search input; v-model and the local computed filter own ordinary text editing. The document listener is passive, so the handler does not call preventDefault. The returned stop function permanently removes its watcher/listener; component scope disposal does the same. SSR has no document host and installs nothing. Search and note values are local and no request or save is sent. This is not a global shortcut on the parent documentation page.

Compare the initial and interacted states
Focus local guide search when typing begins: initial state
Initial state
Focus local guide search when typing begins: state after the verified interactions
After the verified interactions

Copy the example

Save this complete SFC in your Vue project. Its public imports and source are the same ones executed in the preview.

<script setup lang="ts">
import { computed, ref, useId, useTemplateRef } from "vue";
import { onStartTyping } from "@vizejs/composable/on-start-typing";

const searchId = useId();
const search = useTemplateRef<HTMLInputElement>("search");
const query = ref("");
const note = ref("");
const deliveries = ref(0);
const readingActions = ref(0);
const stopped = ref(false);
const guides = ["Compiler guide", "Linter guide", "Keyboard guide"];
const matches = computed(() =>
  guides.filter((guide) => guide.toLowerCase().includes(query.value.toLowerCase())),
);
const stop = onStartTyping(() => {
  deliveries.value += 1;
  search.value?.focus();
});

function stopShortcut(): void {
  stop();
  stopped.value = true;
}
</script>

<template>
  <div class="composable-example">
    <button type="button" @click="() => (readingActions += 1)">Reading control</button>
    <p>Native reading activations: {{ readingActions }}</p>
    <label :for="`${searchId}-query`">Search local guides</label>
    <input :id="`${searchId}-query`" ref="search" v-model="query" type="search" />
    <ul aria-label="Matching local guides">
      <li v-for="guide in matches" :key="guide">{{ guide }}</li>
    </ul>
    <p v-if="matches.length === 0">No local guides match.</p>
    <label :for="`${searchId}-note`">Workshop note</label>
    <input :id="`${searchId}-note`" v-model="note" />
    <button type="button" :disabled="stopped" @click="stopShortcut">Stop typing shortcut</button>
    <output aria-live="polite"
      >Typing shortcut deliveries: {{ deliveries }} · Active: {{ stopped ? "no" : "yes" }}</output
    >
    <p>
      Focus Reading control and press a printable character to focus the search. Space, navigation
      keys, and Ctrl/Meta/Alt shortcuts do not redirect focus. Editing either field stays ordinary
      native typing. Stop removes the shortcut; the fields and local filtering remain usable. This
      preview sends no search request or note save.
    </p>
  </div>
</template>

Runtime contract

Utility Category Stability SSR Hydration Cleanup Targets Host globals Uses
isTypingKeystroke input experimental safe not-applicable none web, server, worker, native, desktop, terminal — —
onStartTyping input experimental deterministic-fallback stable caller, reactive-scope web, desktop document isTypingKeystroke, tryOnScopeDispose

API

isTypingKeystroke

Whether a keyboard event would type a printable character. Single-character keys (letters, digits, punctuation; not space) without ctrl/meta/alt qualify.

function isTypingKeystroke(event: KeyboardEvent): boolean

onStartTyping

Call a handler when the user starts typing while no editable element has focus — typically to focus a search field. Editable means input, textarea, select, or any element with isContentEditable, and elements with role="textbox"/"searchbox"/"combobox". Nothing is registered during server rendering; the listener is removed with the owning scope or the returned stop function.

function onStartTyping( handler: (event: KeyboardEvent) => void, options: OnStartTypingOptions = {}, ): () => void

Types

StartTypingHost

Document-like capability observed by onStartTyping.

Member Type Description
activeElement Element | null Currently focused element.

OnStartTypingOptions

Options for onStartTyping.

Member Type Description
host? MaybeRefOrGetter<StartTypingHost | null | undefined> Reactive document capability for alternate runtimes and tests.