Eingabe & Keymaps

Navigiere mit der Tastatur durch Deployments und füge ein Hilfe-Overlay für ? hinzu.

Die App dieses Kapitels läuft in deiner Konsole. Öffne sie mit ⌘⌥JCtrl+Shift+J⌘⌥KCtrl+Shift+K⌘⌥C (zuerst Entwicklerfunktionen aktivieren), dann probiere sie aus.
Kapitel ansehen3:25

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.

app/deployments/page.tsx+31tsx
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.

▼ 04 · Eingabe & Keymaps

Die Konsole öffnen

⌘⌥J
CtrlShiftJ
⌘⌥K
CtrlShiftK
⌘⌥C

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 Fragen

Beantworte jede Frage, um das Kapitel abzuschließen.

In useKeymap, what does the binding "g g" mean?

 

Warum klickst du vor dem Tippen auf die Seite?