Skip to main content

Function Signature

function useHotkeysContext(): HotkeysContextType
The useHotkeysContext hook provides access to the global hotkeys context, allowing you to view all registered hotkeys and control which scopes are active.

Returns

context
HotkeysContextType
An object containing the hotkeys context state and control functions.Type definition:
type HotkeysContextType = {
  hotkeys: ReadonlyArray<Hotkey>
  activeScopes: string[]
  toggleScope: (scope: string) => void
  enableScope: (scope: string) => void
  disableScope: (scope: string) => void
}

Context Properties

hotkeys
ReadonlyArray<Hotkey>
Array of all currently registered hotkeys across the application.Hotkey type definition:
type Hotkey = KeyboardModifiers & {
  keys?: readonly string[]
  scopes?: Scopes
  description?: string
  isSequence?: boolean
  hotkey: string
  metadata?: Record<string, unknown>
}

type KeyboardModifiers = {
  alt?: boolean
  ctrl?: boolean
  meta?: boolean
  shift?: boolean
  mod?: boolean
  useKey?: boolean
}
activeScopes
string[]
Array of currently active scope names. Hotkeys with matching scopes will be enabled.
The default scope is ['*'] which matches all hotkeys. An empty array means the provider is not set.
enableScope
(scope: string) => void
Function to enable a specific scope.Behavior:
  • If the wildcard scope '*' is active, it will be replaced with the specified scope
  • Otherwise, the scope is added to the active scopes array
  • Duplicate scopes are automatically filtered
disableScope
(scope: string) => void
Function to disable a specific scope. Removes the scope from the active scopes array.
toggleScope
(scope: string) => void
Function to toggle a scope on or off.Behavior:
  • If the scope is currently active, it will be disabled
  • If the scope is not active, it will be enabled
  • If the wildcard scope '*' is active, it will be replaced with the specified scope

HotkeysProvider

To use useHotkeysContext, your components must be wrapped in a HotkeysProvider.

Provider Props

initiallyActiveScopes
string[]
default:"['*']"
Array of scope names that should be active when the provider mounts.The default value ['*'] enables all hotkeys regardless of their scope.
children
ReactNode
required
React children to be wrapped by the provider.

Usage Examples

Basic Setup

import { HotkeysProvider } from 'react-hotkeys-hook'

function App() {
  return (
    <HotkeysProvider>
      <YourApp />
    </HotkeysProvider>
  )
}

With Initial Scopes

import { HotkeysProvider } from 'react-hotkeys-hook'

function App() {
  return (
    <HotkeysProvider initiallyActiveScopes={['editor', 'global']}>
      <YourApp />
    </HotkeysProvider>
  )
}

Viewing Active Hotkeys

import { useHotkeysContext } from 'react-hotkeys-hook'

function HotkeysList() {
  const { hotkeys } = useHotkeysContext()

  return (
    <div>
      <h2>Active Hotkeys</h2>
      <ul>
        {hotkeys.map((hotkey, index) => (
          <li key={index}>
            <strong>{hotkey.hotkey}</strong>
            {hotkey.description && ` - ${hotkey.description}`}
          </li>
        ))}
      </ul>
    </div>
  )
}

Controlling Scopes

import { useHotkeysContext, useHotkeys } from 'react-hotkeys-hook'

function Editor() {
  const { activeScopes, enableScope, disableScope } = useHotkeysContext()

  // This hotkey only works when 'editor' scope is active
  useHotkeys('ctrl+s', () => save(), {
    scopes: ['editor']
  })

  const startEditing = () => enableScope('editor')
  const stopEditing = () => disableScope('editor')

  return (
    <div>
      <button onClick={startEditing}>Start Editing</button>
      <button onClick={stopEditing}>Stop Editing</button>
      <p>Active scopes: {activeScopes.join(', ')}</p>
    </div>
  )
}

Toggling Scopes

import { useHotkeysContext } from 'react-hotkeys-hook'

function ScopeToggle({ scope, label }) {
  const { activeScopes, toggleScope } = useHotkeysContext()
  const isActive = activeScopes.includes(scope)

  return (
    <button onClick={() => toggleScope(scope)}>
      {label}: {isActive ? 'ON' : 'OFF'}
    </button>
  )
}

function App() {
  return (
    <div>
      <ScopeToggle scope="editor" label="Editor Mode" />
      <ScopeToggle scope="viewer" label="Viewer Mode" />
    </div>
  )
}

Multiple Scopes Example

import { HotkeysProvider, useHotkeys, useHotkeysContext } from 'react-hotkeys-hook'

function App() {
  return (
    <HotkeysProvider initiallyActiveScopes={['global']}>
      <Editor />
    </HotkeysProvider>
  )
}

function Editor() {
  const { enableScope, disableScope } = useHotkeysContext()
  const [mode, setMode] = useState('view')

  // Global hotkeys (always active)
  useHotkeys('ctrl+/', () => showHelp(), {
    scopes: ['global']
  })

  // Edit mode hotkeys
  useHotkeys('ctrl+s', () => save(), {
    scopes: ['edit']
  })

  useHotkeys('ctrl+b', () => bold(), {
    scopes: ['edit']
  })

  // View mode hotkeys
  useHotkeys('j', () => scrollDown(), {
    scopes: ['view']
  })

  useHotkeys('k', () => scrollUp(), {
    scopes: ['view']
  })

  const enterEditMode = () => {
    setMode('edit')
    disableScope('view')
    enableScope('edit')
  }

  const enterViewMode = () => {
    setMode('view')
    disableScope('edit')
    enableScope('view')
  }

  return (
    <div>
      <button onClick={enterEditMode}>Edit</button>
      <button onClick={enterViewMode}>View</button>
      <p>Current mode: {mode}</p>
    </div>
  )
}

Building a Hotkey Help Menu

import { useHotkeysContext } from 'react-hotkeys-hook'

function HotkeyHelpMenu() {
  const { hotkeys, activeScopes } = useHotkeysContext()

  // Filter hotkeys by active scopes
  const activeHotkeys = hotkeys.filter(
    (hotkey) =>
      !hotkey.scopes ||
      hotkey.scopes.some((scope) => activeScopes.includes(scope)) ||
      activeScopes.includes('*')
  )

  // Group by metadata category if available
  const grouped = activeHotkeys.reduce((acc, hotkey) => {
    const category = hotkey.metadata?.category || 'General'
    if (!acc[category]) acc[category] = []
    acc[category].push(hotkey)
    return acc
  }, {})

  return (
    <div className="hotkey-help">
      <h2>Keyboard Shortcuts</h2>
      {Object.entries(grouped).map(([category, hotkeys]) => (
        <div key={category}>
          <h3>{category}</h3>
          <ul>
            {hotkeys.map((hotkey, index) => (
              <li key={index}>
                <kbd>{hotkey.hotkey}</kbd>
                <span>{hotkey.description || 'No description'}</span>
              </li>
            ))}
          </ul>
        </div>
      ))}
    </div>
  )
}

Important Notes

The useHotkeysContext hook will return default empty values if used outside of a HotkeysProvider. The activeScopes array will be empty to indicate the provider is not set.
Scopes are case-sensitive. Make sure to use consistent casing when defining and enabling scopes.
When multiple scopes are active, hotkeys that match ANY of the active scopes will be enabled. The wildcard scope '*' matches all hotkeys.

See Also

  • useHotkeys - Main hook for binding keyboard shortcuts
  • Scopes Concept - Learn more about organizing hotkeys with scopes

Build docs developers (and LLMs) love