From a73ce12945d185307bf674ab6b5ff46a9a4f6cf6 Mon Sep 17 00:00:00 2001 From: Tiberiu Ichim Date: Fri, 20 Feb 2026 20:25:32 +0200 Subject: [PATCH] feat: Move to Library dialog with keyboard shortcut buttons + Alt+M shortcut - Replace library dropdown in MoveToLibraryModal with flex-wrap shortcut buttons - Each button has one letter underlined as a keyboard shortcut (greedy first-unused-letter assignment) - Pressing the shortcut key selects the library and immediately triggers the move - If the target library has multiple folders, folder picker appears before moving - Add Alt+M as an alias for the existing Ctrl+Shift+M Move to Library shortcut - Update docs and artifacts index --- .../move_to_library_keyboard_shortcuts.md | 43 +++++++ artifacts/docs/ux_power_user_shortcuts.md | 2 +- artifacts/index.md | 1 + client/components/app/Appbar.vue | 2 +- .../modals/item/MoveToLibraryModal.vue | 108 ++++++++++++++++-- 5 files changed, 145 insertions(+), 11 deletions(-) create mode 100644 artifacts/2026-02-20/move_to_library_keyboard_shortcuts.md diff --git a/artifacts/2026-02-20/move_to_library_keyboard_shortcuts.md b/artifacts/2026-02-20/move_to_library_keyboard_shortcuts.md new file mode 100644 index 000000000..a909c5877 --- /dev/null +++ b/artifacts/2026-02-20/move_to_library_keyboard_shortcuts.md @@ -0,0 +1,43 @@ +# Move to Library — Keyboard Shortcut Buttons + +**Date:** 2026-02-20 + +## Overview + +Replace the dropdown-based library picker in the "Move to Library" dialog with a horizontal row of buttons. Each button represents a target library and has one letter highlighted (underlined) as a keyboard shortcut. Pressing that key immediately selects and executes the move. + +## UX Design + +- Libraries are displayed as **buttons in a horizontal, wrapping row** (flexbox wrap). +- Each button shows the library name with **one letter visually highlighted** (e.g. underlined, bold, or different color) to indicate its keyboard shortcut. +- Letters are assigned greedily: use the **first unused letter** of each library name, scanning left to right. This ensures the mnemonic is intuitive. +- When the dialog is open, pressing a shortcut key triggers the move immediately (same as clicking the button). +- If there are multiple folders in the target library, fall back to the existing folder dropdown before executing. + +## Letter Assignment Algorithm + +``` +used = {} +for each library in targetLibraries: + for each character in library.name: + letter = character.toLowerCase() + if letter is a-z and letter not in used: + assign letter as shortcut + used.add(letter) + break +``` + +## Keyboard Handling + +- Listen for `keydown` events while the dialog is open. +- Match the pressed key against assigned shortcuts (case-insensitive). +- If matched and not processing, trigger `moveItems()` for that library. +- Ignore key events when a child input/select element is focused (e.g., folder dropdown). + +## Visual Button Design + +Each button should: +- Show the library name with the shortcut letter underlined. +- Have a hover/focus state. +- Show an active/selected state when a library is picked. +- The shortcut letter should be highlighted using a `` with distinct styling (underline + slightly different color). diff --git a/artifacts/docs/ux_power_user_shortcuts.md b/artifacts/docs/ux_power_user_shortcuts.md index aa5318661..f9b8d2c31 100644 --- a/artifacts/docs/ux_power_user_shortcuts.md +++ b/artifacts/docs/ux_power_user_shortcuts.md @@ -14,7 +14,7 @@ To improve the efficiency of batch operations, global keyboard listeners have be - **Action Shortcuts** (Context-aware: Applied to selection in Library, or current item on Item Page): - **Consolidate**: `Ctrl + K`. - **Merge**: `Ctrl + M` (Requires 2+ selected items). - - **Move to Library**: `Ctrl + Shift + M`. + - **Move to Library**: `Ctrl + Shift + M` or `Alt + M`. - **Reset Metadata**: `Alt + R`. (Note: `Alt` is used specifically to avoid conflict with standard "Reload" `Ctrl + R`). - **Quick Match / Match**: `Alt + Q`. diff --git a/artifacts/index.md b/artifacts/index.md index b460e4417..68c48c0e4 100644 --- a/artifacts/index.md +++ b/artifacts/index.md @@ -22,6 +22,7 @@ This index provides a quick reference for specification and documentation files | **2026-02-17** | [consolidate_singles.md](2026-02-17/consolidate_singles.md) | Expansion of the "Consolidate" feature to support single-file books by moving them into new folders. | | **2026-02-17** | [ui_enhancements.md](2026-02-17/ui_enhancements.md) | Specification for "View All" shortcuts on Home view shelves with specific sorting. | | **2026-02-20** | [promote_file_to_book.md](2026-02-20/promote_file_to_book.md) | Specification for "promoting" files from an existing book into a standalone library item, including a "Split Book" wizard. | +| **2026-02-20** | [move_to_library_keyboard_shortcuts.md](2026-02-20/move_to_library_keyboard_shortcuts.md) | Specification for keyboard-shortcut-enabled library buttons in the "Move to Library" dialog. | | **General** | [docs/consolidate_feature.md](docs/consolidate_feature.md) | Comprehensive documentation for the "Consolidate" feature, including conflict resolution and technical details. | | **General** | [docs/item_restructuring_guide.md](docs/item_restructuring_guide.md) | Guide for Moving, Merging, and Splitting (Promoting) library items. | | **General** | [docs/metadata_management_tools.md](docs/metadata_management_tools.md) | Documentation for Reset Metadata and Batch Reset operations. | diff --git a/client/components/app/Appbar.vue b/client/components/app/Appbar.vue index 745d7fa3f..52b08cba4 100644 --- a/client/components/app/Appbar.vue +++ b/client/components/app/Appbar.vue @@ -560,7 +560,7 @@ export default { e.preventDefault() this.batchMerge() } - } else if (ctrlOrMeta && shift && e.key.toLowerCase() === 'm') { + } else if ((ctrlOrMeta && shift && e.key.toLowerCase() === 'm') || (alt && e.key.toLowerCase() === 'm')) { e.preventDefault() if (this.numMediaItemsSelected > 0) { this.batchMoveToLibrary() diff --git a/client/components/modals/item/MoveToLibraryModal.vue b/client/components/modals/item/MoveToLibraryModal.vue index a1656b0a6..177c52d88 100644 --- a/client/components/modals/item/MoveToLibraryModal.vue +++ b/client/components/modals/item/MoveToLibraryModal.vue @@ -1,5 +1,5 @@