Collapse algorithm filters into Algos dropdown

- Replace inline filter buttons in desktop header with a single
  "Algos" dropdown that shows all discovery algorithms in a glass
  menu with checkmark for the active selection and a clear option
- Button label dynamically shows the active algorithm name or
  defaults to "Algos" when no filter is active
- Rename mobile tab bar "Filters" to "Algos" with a gear icon
- Rename bottom sheet title to "Algos" to match

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Dorian
2026-02-12 12:35:46 +00:00
parent 0a7543cf32
commit 7c995edcc2
2 changed files with 75 additions and 20 deletions

View File

@@ -13,15 +13,49 @@
<button @click="handleFilmsClick" :class="isRoute('/') && !activeAlgorithm ? 'nav-button-active' : 'nav-button'">Films</button>
<router-link to="/library" :class="isRoute('/library') && !activeAlgorithm ? 'nav-button-active' : 'nav-button'" @click="clearFilter">My List</router-link>
<!-- Algorithm Filters -->
<button
v-for="algo in algorithms"
:key="algo.id"
@click="setAlgorithm(algo.id)"
:class="activeAlgorithm === algo.id ? 'nav-button-active' : 'nav-button'"
>
{{ algo.label }}
</button>
<!-- Algos Dropdown -->
<div class="relative algos-dropdown">
<button
@click="toggleAlgosMenu"
:class="activeAlgorithm ? 'nav-button-active' : 'nav-button'"
>
{{ activeAlgorithmLabel || 'Algos' }}
<svg class="w-3.5 h-3.5 ml-1.5 inline transition-transform" :class="{ 'rotate-180': algosMenuOpen }" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
</svg>
</button>
<div v-if="algosMenuOpen" class="profile-menu absolute left-0 mt-2 w-52">
<div class="floating-glass-header py-2 rounded-xl">
<div class="px-3 py-1 text-xs text-white/40 uppercase tracking-wider">Discovery Algorithms</div>
<button
v-for="algo in algorithms"
:key="algo.id"
@click="handleAlgoSelect(algo.id)"
class="profile-menu-item flex items-center justify-between px-4 py-2.5 w-full text-left"
>
<span>{{ algo.label }}</span>
<svg
v-if="activeAlgorithm === algo.id"
class="w-4 h-4 text-white/80"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
</svg>
</button>
<template v-if="activeAlgorithm">
<div class="border-t border-white/10 my-1"></div>
<button
@click="handleAlgoClear"
class="profile-menu-item flex items-center gap-3 px-4 py-2.5 text-white/50 w-full text-left text-sm"
>
Clear filter
</button>
</template>
</div>
</div>
</div>
</nav>
</div>
@@ -205,23 +239,37 @@ const {
const {
activeAlgorithm,
activeAlgorithmLabel,
algorithms,
setAlgorithm: _setAlgorithm,
} = useContentDiscovery()
/**
* When a filter is clicked, navigate to Films page if not already there,
* then apply the filter.
*/
function setAlgorithm(id: string) {
const dropdownOpen = ref(false)
const personaMenuOpen = ref(false)
const algosMenuOpen = ref(false)
function toggleAlgosMenu() {
algosMenuOpen.value = !algosMenuOpen.value
dropdownOpen.value = false
personaMenuOpen.value = false
}
/** Select an algorithm from the dropdown, navigate to Films if needed */
function handleAlgoSelect(id: string) {
_setAlgorithm(id as any)
algosMenuOpen.value = false
if (route.path !== '/') {
router.push('/')
}
}
const dropdownOpen = ref(false)
const personaMenuOpen = ref(false)
/** Clear the active filter from the dropdown */
function handleAlgoClear() {
if (activeAlgorithm.value) {
_setAlgorithm(activeAlgorithm.value as any) // toggle off
}
algosMenuOpen.value = false
}
const userInitials = computed(() => {
if (nostrActiveName.value) return nostrActiveName.value[0].toUpperCase()
@@ -261,11 +309,13 @@ function clearFilter() {
function toggleDropdown() {
dropdownOpen.value = !dropdownOpen.value
personaMenuOpen.value = false
algosMenuOpen.value = false
}
function togglePersonaMenu() {
personaMenuOpen.value = !personaMenuOpen.value
dropdownOpen.value = false
algosMenuOpen.value = false
}
function navigateTo(path: string) {
@@ -292,12 +342,16 @@ async function handleLogout() {
const handleClickOutside = (event: MouseEvent) => {
const dropdown = document.querySelector('.profile-dropdown')
const personaDropdown = document.querySelector('.persona-dropdown')
const algosDropdown = document.querySelector('.algos-dropdown')
if (dropdown && !dropdown.contains(event.target as Node)) {
dropdownOpen.value = false
}
if (personaDropdown && !personaDropdown.contains(event.target as Node)) {
personaMenuOpen.value = false
}
if (algosDropdown && !algosDropdown.contains(event.target as Node)) {
algosMenuOpen.value = false
}
}
onMounted(() => {