feat: keyboard shortcuts for email navigation

'/' focuses the search bar from anywhere (Layout-level listener).
j/k move focus up/down the email list in FolderView and SearchResults;
e archives the focused email, # trashes it. All shortcuts are ignored
while an input/textarea/select has focus, so typing is never hijacked.

A small hint footer in the bottom-right reminds users of the shortcuts.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
cesnimda
2026-06-30 21:55:36 +02:00
parent c11d747919
commit 7710d49c77
6 changed files with 78 additions and 3 deletions
+3
View File
@@ -4,6 +4,7 @@ import { SearchApi } from '../api/client.js';
import EmailRow from '../components/EmailRow.jsx';
import BulkToolbar from '../components/BulkToolbar.jsx';
import useSelection from '../hooks/useSelection.js';
import useListKeyboardNav from '../hooks/useListKeyboardNav.js';
const FOLDER_META = {
inbox: { icon: '📥', label: 'Inbox' },
@@ -46,6 +47,7 @@ export default function FolderView() {
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const { selected, toggle, clear, removeIds, selectedIds } = useSelection();
const focusedId = useListKeyboardNav(emails, (id) => setEmails((prev) => prev.filter((x) => x.id !== id)));
// Reset when the folder changes
useEffect(() => {
@@ -126,6 +128,7 @@ export default function FolderView() {
email={e}
selected={selected.has(e.id)}
onToggleSelect={toggle}
focused={focusedId === e.id}
onRemove={(id) => setEmails((prev) => prev.filter((x) => x.id !== id))}
/>
))}