Eingabe & Keymaps
Navigiere mit der Tastatur durch Deployments und füge ein Hilfe-Overlay für ? hinzu.
In diesem Kapitel
- `useInput`
- Keymaps
- Das Hilfe-Overlay
- Fokus
Tastendrücke erreichen deine App über ein verborgenes Eingabefeld auf der Seite, deshalb braucht die Seite den Fokus. Darum fordert dich jede Text.js-App auf, zuerst auf die Seite zu klicken. Sobald sie den Fokus hat, erhält React jeden deiner Tastendrücke.
useInput
useInput ist der Low-Level-Hook, den du bisher verwendet hast. Er erhält ein KeyEvent mit einem normalisierten key ("up", "return", "escape"), dem eingegebenen Zeichen in input sowie ctrl, alt, shift und meta.
useInput((e) => { if (e.ctrl && e.key === "k") openPalette();});Rufe e.stopPropagation() auf, damit ein Tastendruck keine Handler weiter unten im Baum erreicht.
Keymaps
Sobald ein Bildschirm mehr als ein paar Tasten nutzt, beschreibe sie mit useKeymap. Tastenbelegungen sind Strings: "up, k" steht für eine der beiden Tasten, "g g" für eine Tastenfolge, "ctrl+k" für eine Tastenkombination. Tastenbelegungen mit Beschriftung erscheinen auch in <KeyHelp>, <KeyHints> und der Befehlspalette.
Hinzugefügt: import { useState } from "react";Hinzugefügt: import { Box, KeyHelp, Text, useKeymap } from "@textjs/app";Hinzugefügt: import { DEPLOYMENTS } from "../../lib/deployments";Hinzugefügt: Hinzugefügt: export default function DeploymentsPage() {Hinzugefügt: const [index, setIndex] = useState(0);Hinzugefügt: const [open, setOpen] = useState(false);Hinzugefügt: const move = (by: number) => setIndex((i) => Math.max(0, Math.min(DEPLOYMENTS.length - 1, i + by)));Hinzugefügt: Hinzugefügt: useKeymap({Hinzugefügt: "up, k": { label: "Previous deployment", run: () => move(-1) },Hinzugefügt: "down, j": { label: "Next deployment", run: () => move(1) },Hinzugefügt: enter: { label: "Toggle details", run: () => setOpen((o) => !o) },Hinzugefügt: "g g": { label: "First deployment", run: () => setIndex(0) },Hinzugefügt: });Hinzugefügt: Hinzugefügt: return (Hinzugefügt: <Box className="flex-row grow p-1 gap-2">Hinzugefügt: <Box className="flex-col grow">Hinzugefügt: {DEPLOYMENTS.map((d, i) => (Hinzugefügt: <Box key={d.id} className="flex-row h-1 gap-2 px-1" backgroundColor={i === index ? "selection" : undefined}>Hinzugefügt: <Text>{i === index ? "›" : " "}</Text>Hinzugefügt: <Text bold={i === index} wrap="truncate-end">{d.commit}</Text>Hinzugefügt: </Box>Hinzugefügt: ))}Hinzugefügt: </Box>Hinzugefügt: {open && <Details deployment={DEPLOYMENTS[index]} />}Hinzugefügt: <KeyHelp />Hinzugefügt: </Box>Hinzugefügt: );Hinzugefügt: }DEPLOYMENTS ist vorerst ein gewöhnliches Array in lib/deployments.ts. Kapitel 6 verlagert es hinter einen Route-Handler.
Das Hilfe-Overlay
<KeyHelp /> reagiert auf ? und öffnet einen modalen Dialog, der alle aktuell aktiven Tastenbelegungen mit Beschriftung gruppiert auflistet. Drücke ? in der Konsole und dann ? oder q, um ihn zu schließen. Tastenbelegungen innerhalb eines modalen Dialogs halten den Fokus fest, sodass die Liste darunter erst wieder reagiert, wenn er geschlossen ist.
Fokus
Komponenten wie <Input>, <Select> und <Table> nehmen Tastendrücke nur an, wenn sie den Fokus haben. Tab verschiebt den Fokus zwischen ihnen; mit useFocus() und useFocusManager() kannst du ihn selbst steuern.
Ausprobieren
Das ist Acme Deploys am Ende des Kapitels, ausgeführt in DevTools. Klicke auf das Pad und nutze dann die Tasten unten.
Die Konsole öffnen
Die App rendert in DevTools.Aktiviere zuerst „Funktionen für Webentwickler anzeigen“ unter Safari Einstellungen → Erweitert. Klicke dann hier und drücke ↓.
Auf einem Desktop öffnen
Diese App rendert in der DevTools-Konsole, die einen Desktop-Browser benötigt.
Quiz
2 FragenBeantworte jede Frage, um das Kapitel abzuschließen.