solid-hotkeys is now part of TanStack Hotkeys
Update: @omniaura/solid-hotkeys is archived. The official Solid adapter now lives inside TanStack Hotkeys as @tanstack/solid-hotkeys. If you are looking for type-safe keyboard shortcuts in SolidJS, use the TanStack package directly.
What happened
I wanted a reactive, type-safe keyboard shortcuts primitive for SolidJS, built on top of TanStack Hotkeys. I spun up a team of coding agents, pointed them at the TanStack core, and let them generate a SolidJS adapter. The result got published as @omniaura/solid-hotkeys.
That was the wrong move. TanStack Hotkeys already had a plan for first-party framework adapters, and the right path was to contribute the Solid adapter upstream, not to ship a parallel package in our own org.
Upstreaming the work
Once I realized the mistake, I opened a PR against the TanStack repo: TanStack/hotkeys#12. KevinVandy took it from there, polished the rough edges, and merged it into the official library.
So the Solid support that @omniaura/solid-hotkeys was trying to provide now ships as part of TanStack Hotkeys itself, maintained alongside the React, Vue, and other adapters.
Use it from TanStack
Install the official package:
npm install @tanstack/solid-hotkeys @tanstack/hotkeys
The core API looks the same as what the original adapter exposed, because that was the shape it was always meant to have:
import { createHotkey } from '@tanstack/solid-hotkeys'
createHotkey("Mod+S", (event) => {
event.preventDefault()
save()
})
Mod automatically maps to Cmd on macOS and Ctrl on Windows and Linux. You get type-safe hotkey strings, Vim-style sequences, key state tracking, and scoped HotkeysProvider support out of the box. The TanStack Hotkeys docs cover the full API.
How we use it in HeyDitto
HeyDitto runs on SolidJS, and @tanstack/solid-hotkeys is wired into the surfaces where keyboard flow matters most. A few real snippets from the app:
Closing a modal with Escape, scoped so it only fires while the modal is mounted:
import { createHotkey } from "@tanstack/solid-hotkeys"
createHotkey("Escape", () => closeModal())
Submitting the compose box with Mod+Enter, only when the modal’s textarea has focus:
createHotkey(
"Mod+Enter",
(e) => {
if (document.activeElement !== textareaRef) return
e.preventDefault()
submit()
},
)
Dismissing the quick-search palette on Escape:
createHotkey(
"Escape",
(e) => {
e.preventDefault()
props.onClose()
},
)
Small code, but it is the difference between an app that feels like a web page and one that feels like a tool. Scoped hotkeys, automatic cleanup on unmount, and the cross-platform Mod modifier mean we stop hand-rolling keydown listeners.
Where to go
- TanStack Hotkeys: tanstack.com/hotkeys/latest
- The upstream PR: TanStack/hotkeys#12
- TanStack ecosystem: tanstack.com/libraries
If you were using @omniaura/solid-hotkeys, swap the import to @tanstack/solid-hotkeys. The adapter will keep getting updates in lockstep with the rest of the TanStack family.
Lesson
When an ecosystem already has a clear home for a contribution, contribute there first. A standalone package made sense for about five minutes. A merged upstream PR is the version that actually lasts.
Thanks to Kevin and the TanStack team for taking the contribution across the finish line.