Rewrote the keyboard shortcut code to remove an unmaintained dependency — PR #35425 (by diondiondion)
GitHub Copilot's explanation of this checkout seemed rather impressive to me:
At checkout 35425 in the Mastodon repository, the former implementation of keyboard shortcuts, which relied on the third-party library react-hotkeys
, has been replaced by a custom React-based solution. Here is a detailed breakdown of the technologies and architectural patterns now used:
1. Custom React Hook and Component
- File Introduced:
app/javascript/mastodon/components/hotkeys/index.tsx
- Key Elements:
- A custom React hook (
useHotkeys
) and a component (Hotkeys
) have been implemented to handle keyboard shortcut logic directly within the application. - This solution leverages React's built-in hooks (
useEffect
,useRef
) for event handling and state management.
2. TypeScript for Type Safety
- TypeScript Usage:
- The new implementation is written in TypeScript, providing stronger type safety and maintainability.
- For example, handler maps are strongly typed, and key matcher logic uses TypeScript types for clarity and correctness.
3. Utility Functions for Key Handling
- File Introduced:
app/javascript/mastodon/components/hotkeys/utils.ts
- Features:
- Utility functions such as
normalizeKey
and type guards likeisKeyboardEvent
help standardize and robustly handle keyboard events across browsers.
4. Storybook Integration for Testing
- File Introduced:
app/javascript/mastodon/components/hotkeys/hotkeys.stories.tsx
- Purpose:
- A Storybook story is included for interactive demonstration and testing of the hotkeys component.
- This enables developers to visually and functionally verify the keyboard shortcut system in isolation.
5. Removal of react-hotkeys
- The dependency on
react-hotkeys
is removed frompackage.json
and corresponding imports are replaced by the new local implementation throughout the codebase.
6. Architectural Improvements
- Matching Logic:
- Hotkey matching logic now supports single-key, combo (modifier + key), and sequence (multi-key) shortcuts, with prioritization for conflict resolution.
- Global vs. Local Scoping:
- The custom component allows for both globally-scoped shortcuts (listening on the document) and locally-scoped ones (within a React component subtree).
- Accessibility:
- The new approach explicitly avoids triggering shortcuts in
<input>
,<textarea>
, and<select>
elements, enhancing usability and accessibility.
7. Modern React Patterns
- The hook-based and functional component design aligns with modern React development best practices, reducing reliance on class components and third-party abstractions.
Summary Table
| Old Tech (Removed) | New Tech (Introduced) |
|----------------------------|-----------------------------------------------|
| react-hotkeys
(NPM lib) | Custom React hook/component (Hotkeys
) |
| JavaScript (in places) | TypeScript |
| Third-party event handling | Native DOM/React event handling & utilities |
| External matching | App-specific matcher logic (TypeScript) |
| No isolated test UI | Storybook-based playground |
References:
- hotkeys/index.tsx (new custom logic)
- hotkeys/utils.ts (key normalization, event guards)
- hotkeys/hotkeys.stories.tsx (Storybook)
In summary:<br />
The Mastodon project at this commit has migrated from a third-party keyboard shortcut library (react-hotkeys
) to a modern, TypeScript-based, locally developed React solution for keyboard shortcut management, offering improved flexibility, maintainability, and testability.