# How to Implement Keyboard Navigation in vue3-otp-input: Backspace, Arrows & Delete

> Learn how to implement keyboard navigation in vue3-otp-input for Backspace, Delete, and Arrow keys. Enhance your OTP input component with automatic handling.

- Repository: [Ejiro Asiuwhu/vue3-otp-input](https://github.com/ejirocodes/vue3-otp-input)
- Tags: how-to-guide
- Published: 2026-03-01

---

**`vue3-otp-input` provides built-in keyboard navigation that handles Backspace, Delete, and Arrow keys automatically through the `handleOnKeyDown` function in the parent component.**

The `ejirocodes/vue3-otp-input` library is a Vue 3 component for one-time password entry that ships with full keyboard accessibility out of the box. Understanding how the internal navigation logic works—located in [`src/components/vue3-otp-input.vue`](https://github.com/ejirocodes/vue3-otp-input/blob/main/src/components/vue3-otp-input.vue)—allows you to customize behavior or extend it with additional event listeners.

## How Keyboard Navigation Works in vue3-otp-input

The component architecture separates concerns between a parent orchestrator and individual input cells. Keyboard events originate in [`single-otp-input.vue`](https://github.com/ejirocodes/vue3-otp-input/blob/main/single-otp-input.vue) but are processed by the parent [`vue3-otp-input.vue`](https://github.com/ejirocodes/vue3-otp-input/blob/main/vue3-otp-input.vue).

**Event flow:**
1. User presses a key in any `<SingleOtpInput />` cell
2. The child component emits the raw `KeyboardEvent` via `@on-keydown`
3. The parent catches this in `handleOnKeyDown(event, index)` and executes navigation logic

The parent component maintains an `activeInput` ref (type `number`) that tracks which cell currently has focus. Helper methods `focusNextInput()`, `focusPrevInput()`, and `focusInput(index)` manage focus movement while clamping values between `0` and `numInputs - 1`.

## Built-in Keyboard Controls

The library recognizes four primary navigation keys defined as constants in the source:

- `BACKSPACE = 8`
- `LEFT_ARROW = 37`
- `RIGHT_ARROW = 39`
- `DELETE = 46`

### Backspace and Delete Behavior

When **Backspace** is pressed, the component:
1. Prevents default browser behavior (`event.preventDefault()`)
2. Clears the current cell value via `changeCodeAtFocus("")`
3. Moves focus to the previous input with `focusPrevInput()`

When **Delete** is pressed, the component only clears the current cell without moving focus, allowing users to remove a character and type a new one in place.

### Arrow Key Navigation

**Left Arrow** triggers `focusPrevInput()`, moving the cursor to the previous cell if one exists. **Right Arrow** triggers `focusNextInput()`, advancing to the next cell. Both actions call `event.preventDefault()` to stop the browser from moving the text cursor within the input field.

## Implementing Custom Keyboard Handlers

While the default behavior covers most accessibility needs, you can listen for additional keys (like **Enter** to submit) by catching the `on-keydown` event emitted by the component.

```vue
<template>
  <vue3-otp-input
    ref="otpInput"
    :num-inputs="6"
    v-model:value="otpValue"
    @on-keydown="handleKeydown"
    @on-complete="handleComplete"
  />
</template>

<script setup lang="ts">
import { ref } from 'vue';
import VOtpInput from 'vue3-otp-input';

const otpValue = ref('');
const otpInput = ref<InstanceType<typeof VOtpInput> | null>(null);

const handleKeydown = (event: KeyboardEvent) => {
  if (event.key === 'Enter') {
    // Submit the OTP programmatically
    console.log('Submitting OTP:', otpValue.value);
    // Add your form submission logic here
  }
};

const handleComplete = (value: string) => {
  console.log('OTP complete:', value);
};
</script>

```

The `on-keydown` event forwards the native `KeyboardEvent` object, allowing you to check `event.key`, `event.keyCode`, or `event.code` for custom logic while preserving the built-in navigation behavior.

## Source Code Reference

The keyboard navigation logic is split across two main component files:

- **[`src/components/vue3-otp-input.vue`](https://github.com/ejirocodes/vue3-otp-input/blob/main/src/components/vue3-otp-input.vue)** – Contains the `handleOnKeyDown` function, `activeInput` state management, and focus helper methods (`focusNextInput`, `focusPrevInput`, `changeCodeAtFocus`).

- **[`src/components/single-otp-input.vue`](https://github.com/ejirocodes/vue3-otp-input/blob/main/src/components/single-otp-input.vue)** – Renders the individual `<input>` element and forwards keyboard events to the parent via `emit('on-keydown', event)`.

The constants for key codes (BACKSPACE, LEFT_ARROW, RIGHT_ARROW, DELETE) are defined at the top of [`vue3-otp-input.vue`](https://github.com/ejirocodes/vue3-otp-input/blob/main/vue3-otp-input.vue) and used in the switch statement within `handleOnKeyDown`.

## Summary

- **vue3-otp-input** provides built-in keyboard navigation for Backspace, Delete, and Arrow keys through the parent component's `handleOnKeyDown` method.
- **Backspace** clears the current cell and moves focus left; **Delete** only clears the current cell.
- **Arrow keys** move focus between cells while preventing default browser cursor movement.
- The navigation state is managed via the `activeInput` ref in [`src/components/vue3-otp-input.vue`](https://github.com/ejirocodes/vue3-otp-input/blob/main/src/components/vue3-otp-input.vue).
- You can extend functionality by listening to the `on-keydown` event for custom keys like Enter.

## Frequently Asked Questions

### Does vue3-otp-input support keyboard navigation by default?

Yes. The component ships with full keyboard accessibility enabled automatically. When users press Backspace, Delete, Left Arrow, or Right Arrow, the `handleOnKeyDown` function in [`src/components/vue3-otp-input.vue`](https://github.com/ejirocodes/vue3-otp-input/blob/main/src/components/vue3-otp-input.vue) processes these events and manages focus movement between the individual input cells without requiring any additional configuration.

### How do I prevent users from editing previous OTP fields?

Enable the `should-focus-order` prop on the component. When set to `true`, the component enforces a forward-only focus order, preventing users from navigating back to previous cells with arrow keys or backspace. The internal `focusOrder` method checks this prop before allowing focus changes initiated by user interaction.

### Can I listen for the Enter key to submit the form?

Yes. While the component handles navigation keys internally, it emits the raw `on-keydown` event for every keystroke. Attach a listener to `@on-keydown` in your parent component and check for `event.key === 'Enter'` to trigger form submission or validation logic while maintaining the built-in navigation behavior.

### Where is the keyboard navigation logic located in the source code?

The primary logic resides in [`src/components/vue3-otp-input.vue`](https://github.com/ejirocodes/vue3-otp-input/blob/main/src/components/vue3-otp-input.vue) inside the `handleOnKeyDown` function, which uses constants for key codes (BACKSPACE=8, LEFT_ARROW=37, RIGHT_ARROW=39, DELETE=46) to determine whether to clear values or shift focus via `focusNextInput()` and `focusPrevInput()`. The child component at [`src/components/single-otp-input.vue`](https://github.com/ejirocodes/vue3-otp-input/blob/main/src/components/single-otp-input.vue) forwards native keyboard events to the parent using `emit('on-keydown', event)`.