feat(ui): add R/F/D action shortcuts and unify keycap hint style

- Bind R=refresh, F=fetch metadata, D=download in PageControls via
  eventManager (plain letters only, skipped while typing or when a
  modal is open); triggers reuse the buttons' existing click handlers
- Show key-hint chips on the refresh/fetch/download/bulk toolbar
  buttons; convert the bulk chip to a semantic <kbd>
- Redesign shortcut hints as a neutral theme-adaptive keycap:
  --shortcut-* variables in base.css now derive from --text-muted
  with a bottom-edge shadow, shared by the toolbar chips, the header
  search cue, the help-modal cheat sheet, and onboarding key hints
- Add shared isTypingContext() helper to uiHelpers
- Add an Actions group (R/F/D) to the Shortcuts cheat-sheet tab

Verified with vitest (926 passing, incl. 6 new shortcut cases) and a
sandboxed E2E run in real Chrome (light/dark rendering, hover state,
'?' opening the Shortcuts tab, clean console)
This commit is contained in:
Will Miao
2026-09-03 19:10:16 +08:00
parent 8260bd022d
commit 726fc178f1
21 changed files with 253 additions and 25 deletions
+14
View File
@@ -311,6 +311,20 @@ export function showActionToast(key, params = {}, type = 'info', options = {}) {
toast.append(closeBtn);
}
/**
* Check whether the event target is a text-entry context (input, textarea,
* select, or contenteditable) where single-letter shortcuts should be treated
* as literal input.
* @param {EventTarget|null} target - The DOM event target
* @returns {boolean}
*/
export function isTypingContext(target) {
if (!(target instanceof Element)) return false;
const tagName = target.tagName?.toLowerCase();
return target.isContentEditable || tagName === 'input' || tagName === 'textarea' || tagName === 'select';
}
export function restoreFolderFilter() {
const activeFolder = getStorageItem('activeFolder');
const folderTag = activeFolder && document.querySelector(`.tag[data-folder="${activeFolder}"]`);