React Example: UseHeldKeys

tsx
import React from 'react'
import ReactDOM from 'react-dom/client'
import {
  formatKeyForDebuggingDisplay,
  useHeldKeys,
  useHeldKeyCodes,
} from '@tanstack/react-hotkeys'
import { HotkeysProvider } from '@tanstack/react-hotkeys'
import { hotkeysDevtoolsPlugin } from '@tanstack/react-hotkeys-devtools'
import { TanStackDevtools } from '@tanstack/react-devtools'
import './index.css'

function App() {
  const heldKeys = useHeldKeys()
  const heldCodes = useHeldKeyCodes()

  // Track history of key combinations
  const [history, setHistory] = React.useState<Array<string>>([])

  React.useEffect(() => {
    if (heldKeys.length > 0) {
      const combo = heldKeys
        .map((k) => formatKeyForDebuggingDisplay(k))
        .join(' + ')
      setHistory((h) => {
        // Only add if different from last entry
        if (h[h.length - 1] !== combo) {
          return [...h.slice(-9), combo]
        }
        return h
      })
    }
  }, [heldKeys])

  console.log('heldKeys', heldKeys)

  return (
    <div className="app">
      <header>
        <h1>useHeldKeys</h1>
        <p>
          Returns an array of all currently pressed keys. Useful for displaying
          key combinations or building custom shortcut recording.
        </p>
      </header>

      <main>
        <section className="demo-section">
          <h2>Currently Held Keys</h2>
          <div className="key-display">
            {heldKeys.length > 0 ? (
              heldKeys.map((key, index) => {
                const code = heldCodes[key]
                return (
                  <React.Fragment key={key}>
                    {index > 0 && <span className="plus">+</span>}
                    <kbd className="large">
                      {formatKeyForDebuggingDisplay(key)}
                      {code && code !== key && (
                        <small className="code-label">
                          {formatKeyForDebuggingDisplay(code, {
                            source: 'code',
                          })}
                        </small>
                      )}
                    </kbd>
                  </React.Fragment>
                )
              })
            ) : (
              <span className="placeholder">Press any keys...</span>
            )}
          </div>
          <div className="stats">
            Keys held: <strong>{heldKeys.length}</strong>
          </div>
        </section>

        <section className="demo-section">
          <h2>Usage</h2>
          <pre className="code-block">{`import { useHeldKeys } from '@tanstack/react-hotkeys'

function KeyDisplay() {
  const heldKeys = useHeldKeys()

  return (
    <div>
      Currently pressed: {heldKeys.join(' + ') || 'None'}
    </div>
  )
}`}</pre>
        </section>

        <section className="demo-section">
          <h2>Try These Combinations</h2>
          <ul>
            <li>
              Hold <kbd>Shift</kbd> + <kbd>Control</kbd> + <kbd>A</kbd>
            </li>
            <li>Press multiple letter keys at once</li>
            <li>Hold modifiers and watch them appear</li>
            <li>Release keys one by one</li>
          </ul>
        </section>

        <section className="demo-section">
          <h2>Recent Combinations</h2>
          {history.length > 0 ? (
            <ul className="history-list">
              {history.map((combo, i) => (
                <li key={i}>{combo}</li>
              ))}
            </ul>
          ) : (
            <p className="placeholder">Press some key combinations...</p>
          )}
          <button onClick={() => setHistory([])}>Clear History</button>
        </section>

        <section className="demo-section">
          <h2>Use Cases</h2>
          <ul>
            <li>Building a keyboard shortcut recorder</li>
            <li>Displaying currently held keys to users</li>
            <li>Debugging keyboard input</li>
            <li>Creating key combination tutorials</li>
          </ul>
        </section>
      </main>

      <TanStackDevtools plugins={[hotkeysDevtoolsPlugin()]} />
    </div>
  )
}

ReactDOM.createRoot(document.getElementById('root')!).render(
  // optionally, provide default options to an optional HotkeysProvider
  <HotkeysProvider
  // defaultOptions={{
  //   hotkey: {
  //     preventDefault: true,
  //   },
  // }}
  >
    <App />
  </HotkeysProvider>,
)