keyboard shortcuts#

global keyboard shortcuts for the plyr.fm frontend.

implementation#

shortcuts are handled in the root layout (frontend/src/routes/+layout.svelte) with context-aware filtering to avoid conflicts with form inputs and other interactive elements.

available shortcuts#

location: frontend/src/routes/+layout.svelte

opens the unified search modal for searching tracks, artists, albums, and tags.

behavior:

  • Cmd+K on macOS, Ctrl+K on windows/linux
  • works from anywhere, including input fields (uses modifier key)
  • toggles search modal open/closed
  • focuses search input automatically on open

in-modal navigation:

  • arrow up/down - navigate results
  • enter - select highlighted result
  • esc - close modal

see search.md for full documentation.


Q - toggle queue#

location: frontend/src/routes/+layout.svelte

toggles the queue sidebar visibility.

behavior:

  • works from any page in the app
  • ignores when modifier keys are pressed (cmd/ctrl/alt)
  • skips when focus is in input/textarea/contenteditable elements
  • persists visibility state to localStorage

desktop: queue opens as 360px fixed sidebar, content shifts left via margin-right: 360px mobile: queue opens as full-screen overlay (no content shift)

accessibility:

  • toggle button includes aria-pressed={showQueue}
  • aria-label="toggle queue (Q)" for screen readers
  • tooltip shows keyboard hint

playback shortcuts#

all playback shortcuts require a track to be loaded and are disabled when the search modal is open.

Space - play/pause#

toggles playback of the current track.

Left Arrow - seek backward#

seeks backward 10 seconds in the current track.

Right Arrow - seek forward#

seeks forward 10 seconds in the current track.

J - previous track#

goes to the previous track in the queue. if more than 3 seconds into the current track, restarts it instead.

L - next track#

advances to the next track in the queue (if available).

M - mute/unmute#

toggles mute. restores previous volume level when unmuting.


adding new shortcuts#

when adding keyboard shortcuts:

  1. add handler to root layout - keeps all shortcuts in one place
  2. filter contexts - check for modifier keys and active element
  3. prevent conflicts - avoid letters used in common form inputs
  4. document behavior - update this file with key, action, and context rules
  5. add accessibility - include aria-labels and tooltips mentioning the shortcut

example pattern#

function handleShortcut(event: KeyboardEvent) {
  // ignore modifiers
  if (event.metaKey || event.ctrlKey || event.altKey) return;

  // ignore in inputs
  const target = event.target as HTMLElement;
  if (
    target.tagName === 'INPUT' ||
    target.tagName === 'TEXTAREA' ||
    target.isContentEditable
  ) return;

  // handle key
  if (event.key.toLowerCase() === 'q') {
    event.preventDefault();
    // do something
  }
}

onMount(() => {
  window.addEventListener('keydown', handleShortcut);
});

onDestroy(() => {
  if (browser) {
    window.removeEventListener('keydown', handleShortcut);
  }
});

future candidates#

potential shortcuts to consider:

  • / - focus search (alternative to Cmd/Ctrl+K)
  • T - cycle theme (dark/light/system)
  • S - shuffle queue

design principles#

  1. global availability - shortcuts should work from anywhere unless context prevents it
  2. respect focus - never intercept input from form fields
  3. progressive disclosure - show hints in tooltips and UI
  4. consistency - follow common web app conventions where possible
  5. accessibility first - keyboard shortcuts enhance but don't replace mouse/touch interaction