Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Apply VueUse composables in Vue 3/Nuxt projects to replace custom implementations with battle-tested utilities.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
references/useMagicKeys.md
1---2category: Sensors3---45# useMagicKeys67Reactive keys pressed state, with magical keys combination support.89## Usage1011```ts12import { useMagicKeys } from '@vueuse/core'1314const { shift, space, a /* keys you want to monitor */ } = useMagicKeys()1516watch(space, (v) => {17if (v)18console.log('space has been pressed')19})2021watchEffect(() => {22if (shift.value && a.value)23console.log('Shift + A have been pressed')24})25```2627::: tip NOTE28If you're using TypeScript with `noUncheckedIndexedAccess` enabled in your `tsconfig.json` (or using Nuxt which enables it by default), the destructured keys will have the type `ComputedRef<boolean> | undefined`.2930The `noUncheckedIndexedAccess` TypeScript option adds `undefined` to any un-declared field accessed via index signatures. Since `useMagicKeys()` uses an index signature to allow accessing any key dynamically, TypeScript will treat destructured properties as potentially undefined for type safety.3132You'll need to use optional chaining or wrap with a getter function:3334```ts35const { shift, space, a } = useMagicKeys()3637watch(38() => space?.value,39(v) => {40if (v)41console.log('space has been pressed')42},43)4445watchEffect(() => {46if (shift?.value && a?.value)47console.log('Shift + A have been pressed')48})49```5051Check the [TypeScript documentation](https://www.typescriptlang.org/tsconfig/#noUncheckedIndexedAccess) for more details about `noUncheckedIndexedAccess`.5253:::5455Check out [all the possible keycodes](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code/code_values).5657### Combinations5859You can magically use combinations (shortcuts/hotkeys) by connecting keys with `+` or `_`.6061```ts62import { useMagicKeys } from '@vueuse/core'6364const keys = useMagicKeys()65const shiftCtrlA = keys['Shift+Ctrl+A']6667watch(shiftCtrlA, (v) => {68if (v)69console.log('Shift + Ctrl + A have been pressed')70})71```7273```ts74import { useMagicKeys } from '@vueuse/core'7576const { Ctrl_A_B, space, alt_s /* ... */ } = useMagicKeys()7778watch(Ctrl_A_B, (v) => {79if (v)80console.log('Control+A+B have been pressed')81})82```8384You can also use `whenever` function to make it shorter8586```ts87import { useMagicKeys, whenever } from '@vueuse/core'8889const keys = useMagicKeys()9091whenever(keys.shift_space, () => {92console.log('Shift+Space have been pressed')93})94```9596### Current Pressed keys9798A special property `current` is provided to representing all the keys been pressed currently.99100```ts101import { useMagicKeys, whenever } from '@vueuse/core'102103const { current } = useMagicKeys()104105console.log(current) // Set { 'control', 'a' }106107whenever(108() => current.has('a') && !current.has('b'),109() => console.log('A is pressed but not B'),110)111```112113### Key Aliasing114115```ts116import { useMagicKeys, whenever } from '@vueuse/core'117118const { shift_cool } = useMagicKeys({119aliasMap: {120cool: 'space',121},122})123124whenever(shift_cool, () => console.log('Shift + Space have been pressed'))125```126127By default, we have some [preconfigured alias for common practices](https://github.com/vueuse/vueuse/blob/main/packages/core/useMagicKeys/aliasMap.ts).128129### Conditionally Disable130131You might have some `<input />` elements in your apps, and you don't want to trigger the magic keys handling when users focused on those inputs. There is an example of using `useActiveElement` and `logicAnd` to do that.132133```ts134import { useActiveElement, useMagicKeys, whenever } from '@vueuse/core'135import { logicAnd } from '@vueuse/math'136137const activeElement = useActiveElement()138const notUsingInput = computed(() =>139activeElement.value?.tagName !== 'INPUT'140&& activeElement.value?.tagName !== 'TEXTAREA',)141142const { tab } = useMagicKeys()143144whenever(logicAnd(tab, notUsingInput), () => {145console.log('Tab has been pressed outside of inputs!')146})147```148149### Custom Event Handler150151```ts152import { useMagicKeys, whenever } from '@vueuse/core'153154const { ctrl_s } = useMagicKeys({155passive: false,156onEventFired(e) {157if (e.ctrlKey && e.key === 's' && e.type === 'keydown')158e.preventDefault()159},160})161162whenever(ctrl_s, () => console.log('Ctrl+S have been pressed'))163```164165> ⚠️ This usage is NOT recommended, please use with caution.166167### Reactive Mode168169By default, the values of `useMagicKeys()` are `Ref<boolean>`. If you want to use the object in the template, you can set it to reactive mode.170171```ts172import { useMagicKeys } from '@vueuse/core'173// ---cut---174const keys = useMagicKeys({ reactive: true })175```176177```vue178<template>179<div v-if="keys.shift">180You are holding the Shift key!181</div>182</template>183```184185## Type Declarations186187```ts188export interface UseMagicKeysOptions<Reactive extends boolean> {189/**190* Returns a reactive object instead of an object of refs191*192* @default false193*/194reactive?: Reactive195/**196* Target for listening events197*198* @default window199*/200target?: MaybeRefOrGetter<EventTarget>201/**202* Alias map for keys, all the keys should be lowercase203* { target: keycode }204*205* @example { ctrl: "control" }206* @default <predefined-map>207*/208aliasMap?: Record<string, string>209/**210* Register passive listener211*212* @default true213*/214passive?: boolean215/**216* Custom event handler for keydown/keyup event.217* Useful when you want to apply custom logic.218*219* When using `e.preventDefault()`, you will need to pass `passive: false` to useMagicKeys().220*/221onEventFired?: (e: KeyboardEvent) => void | boolean222}223export interface MagicKeysInternal {224/**225* A Set of currently pressed keys,226* Stores raw keyCodes.227*228* @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key229*/230current: Set<string>231}232export type UseMagicKeysReturn<Reactive extends boolean> = Readonly<233Record<string, Reactive extends true ? boolean : ComputedRef<boolean>> &234MagicKeysInternal235>236/**237* Reactive keys pressed state, with magical keys combination support.238*239* @see https://vueuse.org/useMagicKeys240*/241export declare function useMagicKeys<T extends boolean = false>(242options?: UseMagicKeysOptions<T>,243): UseMagicKeysReturn<T>244export { DefaultMagicKeysAliasMap } from "./aliasMap"245```246