feat(frontend): keyboard roving-focus and bulk-action keys on the file grid
Arrow keys move a focus ring across the grid (column count derived from the layout, scrolling the focused card into view and pulling the next page near the end). Enter opens the focused file; Space/x select; e edits tags (opening the sheet and focusing its tag filter); p adds to a pool; Del moves to trash — each falling back to the focused card when nothing is selected. / opens the filter and focuses its search. The ring only appears once keyboard navigation starts and is dismissed on pointer use, so it never distracts mouse users. Escape layering is unchanged. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -11,6 +11,8 @@
|
||||
index: number;
|
||||
selected?: boolean;
|
||||
selectionMode?: boolean;
|
||||
/** Roving keyboard-focus ring (shown only during keyboard navigation). */
|
||||
focused?: boolean;
|
||||
onTap?: (e: MouseEvent) => void;
|
||||
/** Called when long-press fires; receives the pointerType of the gesture. */
|
||||
onLongPress?: (pointerType: string) => void;
|
||||
@@ -21,6 +23,7 @@
|
||||
index,
|
||||
selected = false,
|
||||
selectionMode = false,
|
||||
focused = false,
|
||||
onTap,
|
||||
onLongPress
|
||||
}: Props = $props();
|
||||
@@ -108,6 +111,7 @@
|
||||
class="card"
|
||||
class:loaded={!!imgSrc}
|
||||
class:selected
|
||||
class:focused
|
||||
data-file-index={index}
|
||||
onpointerdown={onPointerDown}
|
||||
onpointermove={onPointerMoveInternal}
|
||||
@@ -215,6 +219,12 @@
|
||||
background-color: color-mix(in srgb, var(--color-accent) 35%, transparent);
|
||||
}
|
||||
|
||||
.card.focused {
|
||||
outline: 3px solid var(--color-accent);
|
||||
outline-offset: -3px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.check {
|
||||
position: absolute;
|
||||
top: 6px;
|
||||
|
||||
Reference in New Issue
Block a user