chore: drop static shortcut drawer; inline contextual hints

The bottom-left KeyboardShortcuts drawer duplicated information that
the contextual KeyboardHints pill already shows for the current
selection state. Removing it in favor of the contextual hints alone.

KeyboardHints was previously a fixed top-14 overlay, which collided
with the FilterBar when it was opened — the hints panel covered the
filter controls. Refactored it to render inline in the App header
stack (TopBar / FilterBar / ActiveFilterChips / KeyboardHints /
Timeline) so it flows naturally and never overlaps.

Also:
- Hide hints in loupe mode (the loupe has its own context)
- Replace the deleted shortcuts (Ctrl+A, Trash) with the newly wired
  ones (\\ Filters, / Search, E Loupe) so the hints surface them

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-07 22:15:31 +02:00
parent 6e6672f225
commit 3e322576f2
3 changed files with 26 additions and 167 deletions

View File

@@ -2,27 +2,35 @@ import { usePhotoStore } from '../store/photoStore'
export function KeyboardHints() {
const selectedCount = usePhotoStore((state) => state.selectedPhotos.length)
const viewMode = usePhotoStore((state) => state.viewMode)
const hints = selectedCount > 0 ? [
{ key: '1-5', action: 'Rate' },
{ key: 'P', action: 'Pick' },
{ key: 'X', action: 'Reject' },
{ key: 'Delete', action: 'Trash' },
{ key: 'Esc', action: 'Deselect' },
] : [
{ key: '↑↓←→', action: 'Navigate' },
{ key: 'Click', action: 'Select' },
{ key: 'Shift+Click', action: 'Range' },
{ key: 'Ctrl+A', action: 'Select All' },
{ key: 'Space', action: 'Preview' },
]
// In loupe mode the photo viewer has its own context, so the grid hints
// would just be confusing. Hide them.
if (viewMode === 'loupe') return null
const hints = selectedCount > 0
? [
{ key: '1-5', action: 'Rate' },
{ key: 'P', action: 'Pick' },
{ key: 'X', action: 'Trash' },
{ key: 'E', action: 'Loupe' },
{ key: 'Esc', action: 'Deselect' },
]
: [
{ key: '↑↓←→', action: 'Navigate' },
{ key: 'Click', action: 'Select' },
{ key: 'Shift+Click', action: 'Range' },
{ key: 'Space', action: 'Preview' },
{ key: '\\', action: 'Filters' },
{ key: '/', action: 'Search' },
]
return (
<div className="fixed top-14 left-1/2 z-20 -translate-x-1/2">
<div className="flex items-center gap-3 rounded-full border border-border bg-surface/90 px-4 py-2 shadow-lg backdrop-blur-sm">
<div className="flex justify-center border-b border-border bg-surface/60 px-4 py-1.5">
<div className="flex items-center gap-3">
{hints.map((hint, i) => (
<div key={i} className="flex items-center gap-1.5">
<kbd className="rounded bg-surface-offset px-2 py-0.5 text-xs font-medium text-text">
<kbd className="rounded bg-surface-offset px-2 py-0.5 text-[11px] font-medium text-text">
{hint.key}
</kbd>
<span className="text-xs text-text-muted">{hint.action}</span>
@@ -42,4 +50,4 @@ export function KeyboardHints() {
</div>
</div>
)
}
}