feat(settings): results-only search, keyboard nav, flash animation, Ctrl+F (#264)

Follow-up on #263. Refines the cross-tab search into a proper
command-palette-ish flow and polishes the UX around it.

Results-only mode:
- When a query is active, the tab content is hidden entirely; the
  results list is the only thing shown. Unified list (was: in-place
  current-tab filter + "In other tabs" panel underneath), sorted with
  current-tab matches first and then by score.
- Removed the DOM-based hide/show logic and its CSS helper class, the
  dead searchOtherTabs i18n key, and the searchHits/otherTabHits state.

Keyboard navigation inside the search field:
- ↓/↑ moves selection through the result list (clamped, no wrap).
- Enter activates the selected item (same flow as a click — clears
  query, switches tab, scrolls + opens + flashes the target).
- Mouse hover syncs with the keyboard selection so the two input modes
  don't fight each other.
- Selected item gets accent-border + tinted background; scrollIntoView
  with block:'nearest' keeps it visible when the list is long.

Ctrl/Cmd+F (Settings page only):
- Window keydown listener registered on mount, removed on unmount →
  the shortcut is live only while Settings is rendered.
- Opens the search input, focuses + selects it even if already open.
- preventDefault blocks the native WebKit find bar.
- Placeholder now hints at the shortcut: "… (Ctrl+F)" / "… (⌘F)" on
  macOS, no new i18n keys needed.

Target flash animation:
- After navigating from a result, the target SettingsSubSection gets a
  1.4s accent-colored border + glow pulse so the user immediately sees
  which entry the result pointed at. Reflow trick lets it retrigger
  when clicking the same result twice.

Misc:
- "Next Track Buffering" → "Buffering" in all 8 locales + the section
  comment in Settings.tsx. The SETTINGS_INDEX keeps "next track" as a
  keyword so old search habits still find it.

Co-authored-by: Psychotoxical <dev@psysonic.app>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Frank Stellmacher
2026-04-22 15:12:48 +02:00
committed by GitHub
parent ae7b94f190
commit f0e5b2542b
10 changed files with 139 additions and 105 deletions
+1 -2
View File
@@ -695,7 +695,6 @@ export const frTranslation = {
aboutContributorsCount_other: '{{count}} contributions',
searchPlaceholder: 'Rechercher dans les paramètres…',
searchNoResults: 'Aucun réglage ne correspond à votre recherche.',
searchOtherTabs: 'Dans d\'autres onglets',
aboutMaintainersLabel: 'Mainteneurs',
integrationsPrivacyTitle: 'Avis de confidentialité',
integrationsPrivacyBody: 'Toutes les intégrations de cet onglet sont <strong>facultatives</strong> et, une fois activées, envoient des données à des services externes ou à votre serveur Navidrome. Last.fm reçoit votre historique d\'écoute, Discord affiche le morceau en cours dans votre profil, Bandsintown est interrogé par artiste pour récupérer les dates de tournée, et le partage « En cours de lecture » publie votre morceau actuel auprès des autres utilisateurs de votre serveur Navidrome. Si vous ne voulez rien de tout cela, laissez simplement la section correspondante désactivée.',
@@ -783,7 +782,7 @@ export const frTranslation = {
gaplessDesc: 'Préparer la piste suivante pour éliminer les silences entre les morceaux',
preloadMode: 'Précharger la piste suivante',
preloadModeDesc: 'Quand commencer à mettre en mémoire tampon la piste suivante',
nextTrackBufferingTitle: 'Piste suivante mise en mémoire tampon',
nextTrackBufferingTitle: 'Mise en mémoire tampon',
preloadHotCacheMutualExclusive: "Preload et Hot Cache remplissent le même rôle — un seul peut être actif à la fois. Activer l'un désactive automatiquement l'autre.",
preloadOff: 'Désactivé',
preloadBalanced: 'Équilibré (30 s avant la fin)',