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:
@@ -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 -->
|
||||
<!-- 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="setAlgorithm(algo.id)"
|
||||
:class="activeAlgorithm === algo.id ? 'nav-button-active' : 'nav-button'"
|
||||
@click="handleAlgoSelect(algo.id)"
|
||||
class="profile-menu-item flex items-center justify-between px-4 py-2.5 w-full text-left"
|
||||
>
|
||||
{{ algo.label }}
|
||||
<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(() => {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<div v-if="showFilterSheet" class="filter-sheet-backdrop" @click.self="showFilterSheet = false">
|
||||
<div class="filter-sheet">
|
||||
<div class="filter-sheet-handle"></div>
|
||||
<h3 class="text-white text-base font-semibold mb-4 text-center tracking-wide">Sort By</h3>
|
||||
<h3 class="text-white text-base font-semibold mb-4 text-center tracking-wide">Algos</h3>
|
||||
<div class="flex flex-col gap-2">
|
||||
<button
|
||||
v-for="algo in algorithms"
|
||||
@@ -47,7 +47,7 @@
|
||||
<span class="text-xs font-medium whitespace-nowrap">Films</span>
|
||||
</button>
|
||||
|
||||
<!-- Filters (visible on Films and My List) -->
|
||||
<!-- Algos (visible on Films and My List) -->
|
||||
<button
|
||||
v-if="isOnFilmsPage || isActive('/library')"
|
||||
@click="showFilterSheet = true"
|
||||
@@ -55,9 +55,10 @@
|
||||
:class="{ 'nav-tab-active': isFilterActive || showFilterSheet }"
|
||||
>
|
||||
<svg class="w-6 h-6 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z" />
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.066 2.573c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.573 1.066c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.066-2.573c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z" />
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
|
||||
</svg>
|
||||
<span class="text-xs font-medium whitespace-nowrap">Filters</span>
|
||||
<span class="text-xs font-medium whitespace-nowrap">Algos</span>
|
||||
</button>
|
||||
|
||||
<!-- My List -->
|
||||
|
||||
Reference in New Issue
Block a user