keyboard: board card navigation (j/k/arrows + actions)
Focused-card selection on the board: j/k or arrows move it, Enter opens, e archives, # pins, x trashes the focused card (actions gated off the Trash view). The selection is a brand ring on the card; it scrolls into view and clamps as the list/view changes. A window keydown listener on BoardView, ignored while typing, on a button/link, or while the editor modal is open. Added the card keys to the ? cheat-sheet. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FRgehjoz7Yv8LkUfADxACm
This commit is contained in:
@@ -30,6 +30,9 @@ const shortcuts = [
|
||||
{ label: "Go to Board", keys: ["g", "b"] },
|
||||
{ label: "Go to Graph", keys: ["g", "g"] },
|
||||
{ label: "Go to Reminders", keys: ["g", "r"] },
|
||||
{ label: "Move card focus", keys: ["j", "k"] },
|
||||
{ label: "Open focused card", keys: ["Enter"] },
|
||||
{ label: "Pin / archive / trash card", keys: ["#", "e", "x"] },
|
||||
{ label: "Save & close (editor)", keys: ["⌘/Ctrl", "Enter"] },
|
||||
{ label: "Save & new (composer)", keys: ["Shift", "Enter"] },
|
||||
{ label: "Dismiss / close", keys: ["Esc"] },
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from "vue";
|
||||
import { useNotesStore } from "../stores/notes";
|
||||
import { NOTE_CARD_CLASSES, type NoteColor } from "../notes/colors";
|
||||
import type { Note } from "../stores/notes";
|
||||
@@ -7,7 +8,7 @@ import LinkedText from "./LinkedText.vue";
|
||||
import NoteChecklist from "./NoteChecklist.vue";
|
||||
import { formatReminder, isOverdue } from "../notes/datetime";
|
||||
|
||||
defineProps<{ note: Note; reorderable?: boolean }>();
|
||||
const props = defineProps<{ note: Note; reorderable?: boolean; active?: boolean }>();
|
||||
const emit = defineEmits<{
|
||||
(e: "open", note: Note): void;
|
||||
(e: "dragstart", note: Note): void;
|
||||
@@ -15,6 +16,15 @@ const emit = defineEmits<{
|
||||
}>();
|
||||
const notes = useNotesStore();
|
||||
|
||||
// When this card becomes the keyboard-focused card, scroll it into view.
|
||||
const root = ref<HTMLElement | null>(null);
|
||||
watch(
|
||||
() => props.active,
|
||||
(a) => {
|
||||
if (a) root.value?.scrollIntoView({ block: "nearest", behavior: "smooth" });
|
||||
},
|
||||
);
|
||||
|
||||
function cardClass(color: NoteColor): string {
|
||||
return NOTE_CARD_CLASSES[color] ?? NOTE_CARD_CLASSES.default;
|
||||
}
|
||||
@@ -22,8 +32,9 @@ function cardClass(color: NoteColor): string {
|
||||
|
||||
<template>
|
||||
<div
|
||||
ref="root"
|
||||
class="group relative mb-4 break-inside-avoid rounded-xl border p-3 shadow-sm transition hover:shadow-md"
|
||||
:class="cardClass(note.color)"
|
||||
:class="[cardClass(note.color), active ? 'ring-2 ring-brand' : '']"
|
||||
:draggable="reorderable && !note.trashed"
|
||||
@dragstart="emit('dragstart', note)"
|
||||
@dragover.prevent
|
||||
|
||||
Reference in New Issue
Block a user