How to handle keyboard events in Vue

Keyboard event handling is essential for accessibility, keyboard shortcuts, and improving user experience in web applications. As the creator of CoreUI with over 12 years of Vue.js experience since 2014, I’ve implemented keyboard navigation in countless enterprise applications. Vue provides event listeners with key modifiers to easily capture specific key combinations and keyboard interactions. This approach enables keyboard shortcuts, form navigation, and accessible interfaces without complex event handling code.

Use Vue event listeners with key modifiers to handle keyboard events and create shortcuts.

<template>
  <div>
    <!-- Basic key event -->
    <input
      @keyup='handleKeyPress'
      placeholder='Type something'
    />

    <!-- Specific key with modifier -->
    <input
      @keyup.enter='submitForm'
      placeholder='Press Enter to submit'
    />

    <!-- Key combinations -->
    <div
      @keydown.ctrl.s.prevent='saveDocument'
      @keydown.meta.s.prevent='saveDocument'
      tabindex='0'
      class='editor'
    >
      Press Ctrl+S (Cmd+S on Mac) to save
    </div>

    <!-- Multiple keys -->
    <input
      @keyup.enter='search'
      @keyup.esc='clearSearch'
      v-model='searchQuery'
      placeholder='Search (Enter) or clear (Esc)'
    />

    <!-- Arrow keys -->
    <div
      @keydown.up='moveUp'
      @keydown.down='moveDown'
      @keydown.left='moveLeft'
      @keydown.right='moveRight'
      tabindex='0'
      class='game-area'
    >
      Use arrow keys to move
    </div>

    <!-- Modifier keys -->
    <button
      @click.ctrl='handleCtrlClick'
      @click.shift='handleShiftClick'
      @click.alt='handleAltClick'
    >
      Click with modifiers
    </button>

    <!-- Global keyboard shortcuts -->
    <div class='app'>
      {{ message }}
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted } from 'vue'

const searchQuery = ref('')
const message = ref('Press Ctrl+K to focus search')

const handleKeyPress = (event) => {
  console.log('Key pressed:', event.key)
  console.log('Code:', event.code)
  console.log('Ctrl:', event.ctrlKey)
  console.log('Shift:', event.shiftKey)
  console.log('Alt:', event.altKey)
}

const submitForm = () => {
  console.log('Form submitted with Enter key')
}

const saveDocument = () => {
  console.log('Document saved')
  message.value = 'Document saved!'
}

const search = () => {
  console.log('Searching for:', searchQuery.value)
}

const clearSearch = () => {
  searchQuery.value = ''
  console.log('Search cleared')
}

const moveUp = () => console.log('Moving up')
const moveDown = () => console.log('Moving down')
const moveLeft = () => console.log('Moving left')
const moveRight = () => console.log('Moving right')

const handleCtrlClick = () => console.log('Ctrl + Click')
const handleShiftClick = () => console.log('Shift + Click')
const handleAltClick = () => console.log('Alt + Click')

// Global keyboard shortcuts
const handleGlobalKeydown = (event) => {
  // Ctrl+K or Cmd+K to focus search
  if ((event.ctrlKey || event.metaKey) && event.key === 'k') {
    event.preventDefault()
    document.querySelector('input[type="text"]')?.focus()
  }

  // Escape to close modals
  if (event.key === 'Escape') {
    console.log('Escape pressed globally')
  }

  // Ctrl+/ for help
  if ((event.ctrlKey || event.metaKey) && event.key === '/') {
    event.preventDefault()
    console.log('Show help')
  }
}

onMounted(() => {
  window.addEventListener('keydown', handleGlobalKeydown)
})

onUnmounted(() => {
  window.removeEventListener('keydown', handleGlobalKeydown)
})
</script>

<style scoped>
.editor,
.game-area {
  padding: 20px;
  border: 2px solid #ddd;
  margin: 10px 0;
  outline: none;
}

.editor:focus,
.game-area:focus {
  border-color: #007bff;
}

input {
  padding: 8px;
  margin: 10px 0;
  width: 100%;
}
</style>

Key modifiers available:

<!-- Exact key -->
@keyup.enter
@keyup.tab
@keyup.delete
@keyup.esc
@keyup.space
@keyup.up
@keyup.down
@keyup.left
@keyup.right

<!-- System modifiers -->
@keyup.ctrl
@keyup.alt
@keyup.shift
@keyup.meta  <!-- Cmd on Mac, Windows key on PC -->

<!-- Combinations -->
@keydown.ctrl.enter
@keydown.shift.delete
@keydown.alt.s

<!-- Prevent default -->
@keydown.ctrl.s.prevent

Best Practice Note

Use @keydown for actions that should trigger immediately and @keyup for actions after key release. Always use .prevent modifier with keyboard shortcuts to prevent default browser behavior (like Ctrl+S opening save dialog). Add tabindex='0' to non-input elements to make them focusable for keyboard events. Use event.metaKey to detect Cmd on Mac and Windows key on PC. Clean up global event listeners in onUnmounted to prevent memory leaks. This is how we implement keyboard navigation in CoreUI for Vue—providing accessible shortcuts, form navigation, and power-user features in enterprise dashboards and admin interfaces.


Speed up your responsive apps and websites with fully-featured, ready-to-use open-source admin panel templates—free to use and built for efficiency.


About the Author

Subscribe to our newsletter
Get early information about new products, product updates and blog posts.
How to Remove Underline from Link in CSS
How to Remove Underline from Link in CSS

How to concatenate a strings in JavaScript?
How to concatenate a strings in JavaScript?

How to Add a Tab in HTML
How to Add a Tab in HTML

How to Open Link in a New Tab in HTML?
How to Open Link in a New Tab in HTML?

Answers by CoreUI Core Team