Don't have TanStack Hotkeys installed yet? See the Installation page for instructions.
Use createHotkey for global shortcuts and attachments for element-scoped shortcuts.
<script lang="ts">
import { createHotkey } from '@tanstack/svelte-hotkeys'
createHotkey('Mod+S', () => {
saveDocument()
})
</script>
<div>Press Cmd+S (Mac) or Ctrl+S (Windows) to save</div>
The Mod modifier automatically resolves to Meta (Command) on macOS and Control on Windows/Linux, so your shortcuts work across platforms without extra logic.
<script lang="ts">
import { createHotkey } from '@tanstack/svelte-hotkeys'
createHotkey('Mod+S', () => save())
createHotkey('Mod+Z', () => undo())
createHotkey('Mod+Shift+Z', () => redo())
createHotkey('Mod+F', () => openSearch())
createHotkey('Escape', () => closeDialog())
</script>
<script lang="ts">
import { createHotkeyAttachment } from '@tanstack/svelte-hotkeys'
const closePanel = createHotkeyAttachment('Escape', () => {
close()
})
</script>
<div tabindex="0" {@attach closePanel}>
<p>Press Escape while focused here to close</p>
</div>
<script lang="ts">
import { createHotkey } from '@tanstack/svelte-hotkeys'
let isOpen = $state(true)
createHotkey(
'Escape',
() => {
isOpen = false
},
() => ({ enabled: isOpen }),
)
</script>
<script lang="ts">
import { createHotkeySequenceAttachment } from '@tanstack/svelte-hotkeys'
const vimKeys = createHotkeySequenceAttachment(['G', 'G'], () => {
scrollToTop()
})
</script>
<div tabindex="0" {@attach vimKeys}>
Focus here, then press g then g
</div>
<script lang="ts">
import { getHeldKeys, getIsKeyHeld } from '@tanstack/svelte-hotkeys'
const heldKeys = getHeldKeys()
const isShiftHeld = getIsKeyHeld('Shift')
</script>
<div class="status-bar">
{#if isShiftHeld.held}<span>Shift mode active</span>{/if}
{#if heldKeys.keys.length > 0}
<span>Keys: {heldKeys.keys.join('+')}</span>
{/if}
</div>
<script lang="ts">
import {
createHotkeyRecorder,
formatForDisplay,
} from '@tanstack/svelte-hotkeys'
const recorder = createHotkeyRecorder({
onRecord: (hotkey) => {
console.log('Recorded:', hotkey)
},
})
</script>
<button onclick={recorder.startRecording}>
{recorder.recordedHotkey
? formatForDisplay(recorder.recordedHotkey)
: 'Click to record'}
</button>
<script lang="ts">
import { formatForDisplay, createHotkey } from '@tanstack/svelte-hotkeys'
createHotkey('Mod+S', () => save())
</script>
<button>
Save <kbd>{formatForDisplay('Mod+S')}</kbd>
</button>
Use setHotkeysContext when you want defaults for a subtree. This is an advanced API and usually belongs near the root of the part of the app that owns the hotkeys.
<script lang="ts">
import { setHotkeysContext } from '@tanstack/svelte-hotkeys'
setHotkeysContext({
hotkey: { preventDefault: true },
hotkeySequence: { timeout: 1500 },
})
</script>