Skip to main content
Open Tarteel supports keyboard navigation to help you browse and control the app efficiently without a mouse. Master these shortcuts to enhance your workflow.

Reciter List Navigation

The reciter list supports full keyboard navigation for quick browsing:

Arrow Keys

Action: Move focus to the next reciter in the listBehavior:
  • If no item is focused, focuses the first reciter
  • If the last item is focused, wraps to the first reciter
  • Automatically scrolls the focused item into view
  • Smooth scrolling animation for better visual tracking
Implementation: src/hooks/use-keyboard-navigation.ts:18-23
case 'ArrowDown':
  event.preventDefault();
  setFocusedIndex((previous) =>
    previous === null || previous === itemCount - 1 
      ? 0 
      : previous + 1
  );
Action: Move focus to the previous reciter in the listBehavior:
  • If no item is focused, focuses the last reciter
  • If the first item is focused, wraps to the last reciter
  • Automatically scrolls the focused item into view
  • Smooth scrolling animation
Implementation: src/hooks/use-keyboard-navigation.ts:25-30
case 'ArrowUp':
  event.preventDefault();
  setFocusedIndex((previous) =>
    previous === null || previous === 0 
      ? itemCount - 1 
      : previous - 1
  );
Action: Return focus to the search input fieldBehavior:
  • Clears current focus from reciter list
  • Focuses the search input at the top of the page
  • Allows immediate typing to search for reciters
  • Does not close any open menus or modals
Implementation: src/hooks/use-keyboard-navigation.ts:32-36
case 'Escape':
  setFocusedIndex(null);
  searchInputRef.current?.focus();
Keyboard navigation is implemented in useKeyboardNavigation hook and automatically prevents default browser scrolling behavior for arrow keys.

Auto-Scrolling

When you navigate with arrow keys, the focused reciter automatically scrolls into view:
reciterReferences.current[focusedIndex]?.scrollIntoView({
  behavior: 'smooth',
  block: 'nearest',
  inline: 'start',
});
Scroll Behavior:
  • Smooth: Animated scrolling for better visual tracking
  • Block: nearest: Minimal scrolling - only scrolls if item is out of view
  • Inline: start: Aligns to the start edge for RTL/LTR support
The smart scrolling algorithm only scrolls when necessary, keeping the interface stable while ensuring the focused item is always visible.

Focus Management

The keyboard navigation system manages focus state:
  • Focused Index: Tracks which reciter is currently focused (0-based index or null)
  • Reciter Refs: Array of references to reciter button elements
  • Search Input Ref: Reference to the search input field for Escape key
State Management:
const [focusedIndex, setFocusedIndex] = useState<number | null>(null);

Circular Navigation

Arrow key navigation wraps around at list boundaries:
  • At Bottom: Arrow Down wraps to the first item
  • At Top: Arrow Up wraps to the last item
  • No Selection: First arrow key focuses appropriate end of list
Circular navigation ensures you can quickly reach any reciter regardless of list length.

Browser Shortcuts

Standard browser keyboard shortcuts also work in Open Tarteel:

Fullscreen

ShortcutAction
F11Toggle fullscreen mode (Windows/Linux)
Fn + F11Toggle fullscreen mode (macOS)
EscapeExit fullscreen mode (all platforms)
Browser fullscreen (F11) is different from the app’s fullscreen mode. Browser fullscreen removes all browser UI, while app fullscreen simplifies the player interface but keeps the browser chrome.
ShortcutAction
SpaceScroll down one page
Shift + SpaceScroll up one page
HomeScroll to top of page
EndScroll to bottom of page
Page UpScroll up one viewport
Page DownScroll down one viewport

Search and Selection

ShortcutAction
Ctrl/Cmd + FOpen browser’s find-in-page
TabMove focus to next interactive element
Shift + TabMove focus to previous interactive element
EnterActivate focused button or link
Use Tab/Shift+Tab to navigate through player controls and buttons when not using the custom arrow key navigation.

Accessibility Features

Keyboard navigation enhances accessibility:

Screen Reader Support

  • All interactive elements have proper ARIA labels
  • Focus changes are announced by screen readers
  • Current state (playing, paused, etc.) is accessible
  • Button purposes are clearly labeled
Example ARIA Labels:
aria-label={isPlaying ? messages.pause : messages.play}
aria-label={messages.nextTrack}
aria-label={messages.previousTrack}

Keyboard-Only Operation

The entire app can be operated without a mouse:
1

Navigate Reciters

Use Arrow Up/Down to browse the reciter list
2

Select Reciter

Press Enter when focused on a reciter to select them
3

Control Playback

Tab to player controls and use Enter/Space to activate buttons
4

Search

Press Escape to return to search field and type to filter reciters

Visual Focus Indicators

Focused elements display clear visual indicators:
  • Outline or border on focused interactive elements
  • Different styling for keyboard focus vs mouse hover
  • High contrast focus indicators for visibility
  • Focus rings respect system preferences
Focus indicators follow accessibility guidelines for contrast ratios and visibility.

Implementation Details

Hook: useKeyboardNavigation

Location: src/hooks/use-keyboard-navigation.ts Parameters:
  • itemCount: number - Total number of reciters in the list
Returns:
{
  focusedIndex: number | null;           // Current focused index
  setFocusedIndex: (index: number | null) => void;  // Focus setter
  reciterRefs: RefObject<(HTMLElement | null)[]>;   // Reciter elements
  searchInputRef: RefObject<HTMLInputElement | null>; // Search input
}

Event Handling

Keyboard events are handled at the window level:
window.addEventListener('keydown', handleKeyDown);
Benefits:
  • Works regardless of which element has focus
  • Consistent behavior across the entire app
  • Properly cleaned up on component unmount
The keyboard handler returns early if itemCount === 0 to prevent errors when the reciter list is empty.

Focus Effects

Focus changes trigger effects to update the UI:
useEffect(() => {
  if (focusedIndex !== null) {
    reciterReferences.current[focusedIndex]?.scrollIntoView({
      behavior: 'smooth',
      block: 'nearest',
      inline: 'start',
    });
    reciterReferences.current[focusedIndex]?.focus();
  }
}, [focusedIndex]);
Effect Actions:
  1. Scrolls focused element into view
  2. Applies browser focus to the element
  3. Only runs when focus index changes

Best Practices

Fast Navigation

Use Arrow keys for quick browsing through reciters instead of scrolling and clicking

Quick Search

Press Escape from anywhere to jump to search and filter the list

Fullscreen Focus

Press F11 for fullscreen mode when you want distraction-free listening

Combine Methods

Mix keyboard and mouse navigation - use whatever feels most efficient
Power users can navigate the entire app using only the keyboard: Arrow keys for list navigation, Enter to select, Tab for controls, and Space to play/pause.

Future Shortcuts

While not currently implemented, these shortcuts would enhance the experience:
Proposed ShortcutSuggested Action
SpacePlay/Pause toggle
(Right Arrow)Next track (when not in list)
(Left Arrow)Previous track (when not in list)
MMute/unmute volume
FToggle fullscreen
VToggle visualizer
LToggle playlist
+/-Increase/decrease volume
0-9Jump to percentage of track
These shortcuts could be added in future versions. Consider contributing to the project if you’d like to implement them!

Build docs developers (and LLMs) love