00:00:00TanStack hat ein weiteres Paket veröffentlicht, in ihrem Bestreben, die JavaScript-Welt zu verbessern,
00:00:03und dieses Mal nehmen sie sich die Hotkeys vor. Falls ihr denkt, das klingt
00:00:07einfach und KI könnte das heutzutage sicher locker schreiben: weit gefehlt. TanStack Hotkeys
00:00:11behandelt all die Sonderfälle, die KI oft übersieht, wie verschiedene Tastaturlayouts, Betriebssysteme,
00:00:16konfligierende Hotkeys, überschneidende Scopes und vieles mehr – es bietet sogar Funktionen
00:00:20wie Hotkey-Sequenzen und -Aufzeichnung, und das alles typsicher und Framework-agnostisch.
00:00:26Glaubt mir, wenn ihr Hotkeys braucht, nutzt dieses Paket oder sagt es eurem KI-Agenten.
00:00:30Es ist von TanStack, die Developer Experience wird also top sein. Schauen wir uns das Ganze
00:00:35jetzt mal direkt in Aktion an.
00:00:41Ich springe direkt in den Code, da alles ziemlich unkompliziert ist. Ich zeige das hier
00:00:45in einer React-Anwendung und nutze daher das @tanstack/react-hotkeys Paket.
00:00:49Es gibt aktuell auch ein Vanilla-JavaScript-Paket, und weitere Frameworks
00:00:52sollen bald folgen. Da es noch in der Alpha-Phase ist, gibt es vielleicht hier und da
00:00:56noch Bugs, aber für meine Zwecke hat es bereits alles gelöst. Beginnen wir
00:01:01mit dem einfachsten Anwendungsfall: dem useHotkey-Hook. Hier unten haben wir ihn
00:01:05importiert. Wir müssen nur definieren, was unser Hotkey ist, und eine
00:01:09Funktion angeben, die beim Drücken ausgeführt wird. In meinem Fall soll
00:01:13beim Drücken eine Befehlspalette geöffnet werden – ein klassisches Beispiel.
00:01:17Hier unten seht ihr einen Toast, damit ihr genau verfolgen könnt, was ich gedrückt habe
00:01:20und was dadurch passiert ist. Wie ihr seht, ist dieser Hook extrem simpel,
00:01:24er macht genau das, was er soll. Die Magie bei TanStack liegt meistens in der
00:01:28Developer Experience und der Typsicherheit, und das ist hier nicht anders. Zuerst
00:01:32geht es mit den Hotkeys los: Überall im Paket ist die Definition typsicher,
00:01:37was echt Wahnsinn ist. Es kennt alle möglichen Tasten und Kombinationen.
00:01:41Ich könnte das in etwas wie "meta + s" ändern, was auf macOS "Command + S" entspricht.
00:01:46Wenn ich also einen Hotkey zum Speichern erstelle, erkennt es, dass dies eine
00:01:50gültige Kombi ist. Vertippe ich mich, gibt es einen Type-Error, der uns warnt,
00:01:54dass der Hotkey ungültig ist. Ein weiteres cooles Feature der Hotkey-Definition:
00:01:58Aktuell ist es auf "meta + k" eingestellt, also "Command + K" auf macOS.
00:02:02Das funktioniert bei mir, da ich am Mac sitze, aber auf Windows oder anderen
00:02:06Plattformen würde dieser Hotkey nicht funktionieren, da es dort keine Meta-Taste gibt.
00:02:11Stattdessen können wir die Meta-Taste durch die "mod"-Taste (Modifier) ersetzen.
00:02:15Das bedeutet: Auf macOS wird automatisch Command verwendet, auf allen
00:02:19anderen Plattformen wird daraus Control. So habt ihr sofort einen plattformübergreifenden Hotkey.
00:02:24Und was die Definition der Hotkeys in diesem Paket angeht:
00:02:27Falls ihr keine Strings mögt, könnt ihr auch eine Objekt-Definition nutzen.
00:02:31Das ist genau die gleiche Tastenkombination wie zuvor (Cmd + K oder Strg + K).
00:02:35Wir geben einfach die Haupttaste an und setzen "mod" auf "true", falls gewünscht,
00:02:38oder eben andere Modifier-Tasten. Aber weg von der Definition des Hotkeys,
00:02:42schauen wir uns das nächste Argument des Hooks an: die eigentliche Funktion,
00:02:46die beim Drücken ausgeführt wird. Das ist natürlich sehr einfach gehalten.
00:02:50Ihr könnt darin tun, was ihr wollt, habt aber auch Zugriff auf das rohe
00:02:54Keyboard-Event, falls nötig, sowie auf einen Kontext. Dieser Kontext
00:02:58liefert euch den Hotkey als String zurück oder auch den
00:03:02ausgelösten Hotkey als Objekt-Definition, wie wir sie gerade gesehen haben.
00:03:05Es gibt noch viel mehr zu zeigen, aber das dritte Argument des useHotkey-Hooks
00:03:09sind Optionen, um das Verhalten zu steuern. Die meisten sind
00:03:13selbsterklärend und ich habe sie auf den Standards belassen. Es gibt "enabled"
00:03:17für die programmatische Steuerung, oder "eventType", um festzulegen,
00:03:21ob auf "keydown" oder "keyup" reagiert wird. "requireReset" bedeutet:
00:03:25Wenn es auf "false" steht und ich Cmd + K gedrückt halte, wird der Hotkey
00:03:29ständig neu ausgelöst. Setze ich es jedoch auf "true", müssen wir die
00:03:33Tasten erst loslassen, bevor sie erneut triggern. Ich halte sie gerade gedrückt
00:03:37und es wurde diesmal nur einmal ausgelöst. Dann haben wir "ignoreInputs".
00:03:41Das bedeutet: Wenn ich mich in einem Eingabefeld befinde und Cmd + K drücke,
00:03:45wird das aktuell ignoriert und der Hotkey nicht ausgelöst. Das könnten wir auf
00:03:49"false" setzen, falls Hotkeys auch in Inputs funktionieren sollen.
00:03:53Die letzte Option, die ich hier bespreche, ist "target". Damit lassen sich
00:03:57lokal begrenzte Hotkeys (Scoped Hotkeys) erstellen. Standardmäßig gilt das gesamte
00:04:00Dokument, ich kann Cmd + K also überall auf der Seite drücken, um die Palette zu öffnen.
00:04:04Ich kann das aber auf ein Element oder eine React-Ref ändern. Wenn ich es
00:04:09zum Beispiel auf die "badgeRef" ändere, werdet ihr sehen: Klicke ich irgendwo anders
00:04:13und drücke Cmd + K, passiert nichts. Fokussiere ich jedoch mein
00:04:17Badge-Element hier unten, funktioniert es. Wir haben jetzt also einen Scoped Hotkey.
00:04:21Hoffentlich seht ihr schon, warum ich dieses Paket mag: Diese Liebe zum Detail,
00:04:25die tolle DX und die komplette Typsicherheit. Und dabei habe ich erst einen
00:04:30Hook gezeigt. Schauen wir uns weitere an. Als Nächstes: useHotkeySequences.
00:04:34Damit sind Tastenfolgen möglich, etwa für Navigation im Vim-Stil.
00:04:38Auch dieser ist selbsterklärend und ähnlich wie useHotkey. Wir definieren
00:04:43einfach die Tastenfolge und dann die Funktion, die nach der Eingabe
00:04:47ausgeführt werden soll. In den Optionen gibt es zudem den "timeout",
00:04:51also die Zeitspanne zwischen den Tastenschlägen, damit sie noch als
00:04:54Sequenz erkannt werden. Ich habe hier "gg" eingestellt, um zum Anfang
00:04:59der Liste zu springen. Wenn ich jetzt "gg" drücke, passiert genau das.
00:05:04Unten habe ich noch "sub" eingerichtet, was zum Ende der Liste springt –
00:05:09rein zufällig ergibt das das Wort "subscribe", was ihr definitiv tun solltet.
00:05:12Kommen wir zu noch simpleren Hooks. Der erste ist "useKeyHold". Hier gibt man
00:05:16nur an, welche Taste man tracken will, und erhält einen Boolean-Wert zurück,
00:05:20ob die Taste gerade gedrückt gehalten wird oder nicht. Ich überwache hier ein paar davon.
00:05:24Wenn ich Shift und Alt halte, ändert sich der Status auf der Seite basierend auf diesem Boolean.
00:05:28Euch ist sicher aufgefallen, dass ich unten alle aktuell gedrückten Tasten aufliste.
00:05:32Das kommt vom zweiten Hook, "useHeldKeys", welcher einfach ein Array
00:05:36der aktuell gedrückten Tasten zurückgibt. Wenn ich "sub" halte, erscheint es
00:05:40in diesem Array. Und der letzte Hook, bevor wir zu den coolen
00:05:43Utility-Funktionen kommen, ist "useHotkeyRecorder". Damit lassen sich
00:05:47UIs zur Anpassung von Tastenkürzeln erstellen. Ein sehr praktischer Helfer-Hook,
00:05:52der auch sehr einfach zu bedienen ist. Wir nutzen useHotkeyRecorder und
00:05:56erhalten Werte wie den Aufnahmestatus, den aufgezeichneten Hotkey sowie Funktionen
00:06:00zum Starten und Abbrechen der Aufnahme. In den Optionen des Hooks
00:06:05können wir festlegen, was bei einer erfolgreichen Aufnahme passieren soll.
00:06:09In meinem Fall setze ich den Hotkey für die Palette auf das, was der User
00:06:14gewählt hat. Wenn wir das mit einem Button verknüpfen, sieht das UI etwa so aus:
00:06:17Aktuell öffnet Cmd + K die Palette, aber wenn ich auf "Record" klicke,
00:06:21lauscht der Hook auf meine Tastatur. Drücke ich Cmd + Backspace, ist das mein
00:06:26neuer Hotkey für die Palette. Normalerweise würde man das in einer Datenbank
00:06:29speichern, damit die Einstellungen des Users erhalten bleiben. Ein super nützlicher Hook,
00:06:33der wie die anderen einfach zu bedienen ist und tolle Defaults hat,
00:06:37etwa dass ein auf macOS mit der Command-Taste aufgenommener Hotkey
00:06:42automatisch in die "mod"-Taste umgewandelt wird, was auf Windows oder Linux dann Control entspricht.
00:06:46Neben den Hooks gibt es noch ein paar Dinge, die ich euch zeigen möchte,
00:06:49wie zum Beispiel die Funktionen zur Formatierung. Wir haben hier
00:06:53eine Funktion namens "formatForDisplay" aus dem TanStack-Paket. Sie erlaubt uns,
00:06:57einen Hotkey wie "mod + backspace" einzugeben, der dann automatisch
00:07:02an die Plattform des Users und die entsprechenden Icons angepasst wird (hier Cmd + Backspace).
00:07:06Auf Windows würde es als "Ctrl + Backspace" angezeigt. Dann gibt es noch
00:07:10"formatWithLabels", was im Grunde genau dasselbe macht, nur dass
00:07:14die Modifier-Taste als Text-Label statt als Icon ausgegeben wird.
00:07:18Also "Command Backspace" hier, oder eben "Control Backspace" unter Windows.
00:07:22Einer der Gründe, warum ich TanStack liebe, sind die Devtools, und dieses Paket
00:07:27macht da keine Ausnahme. Öffnen wir die Devtools, sehen wir alle registrierten
00:07:30Hotkeys und Sequenzen der Seite samt Status und wie oft sie ausgelöst wurden.
00:07:33Man sieht, ob auf Keydown oder Keyup reagiert wird, ob auf dem gesamten
00:07:37Dokument oder einem speziellen Element gelauscht wird, und man findet
00:07:41weitere Details wie die konfigurierten Optionen. Man kann sogar einen
00:07:45manuellen Trigger auslösen. Oben werden zudem die aktuell gedrückten Tasten
00:07:49angezeigt. Wenn ihr also bei der Einrichtung nicht wisst, wie eine Taste heißt,
00:07:52drückt sie einfach hier und seht den genauen Wert. Ich klinge vielleicht wie eine
00:07:56kaputte Schallplatte, aber TanStack versteht Developer Experience einfach.
00:08:00Ich freue mich sehr, dass wir so etwas auch in Zeiten von KI-Coding noch bekommen.
00:08:05Schaut euch das Paket unbedingt mal an, falls ihr es braucht, und schreibt mir
00:08:08eure Meinung in die Kommentare. Vergesst nicht zu abonnieren und bis zum nächsten Mal!