Skip to content

Commit 70a16e8

Browse files
committed
feat: optimize the filter popover
1 parent 79f4834 commit 70a16e8

1 file changed

Lines changed: 82 additions & 24 deletions

File tree

app/pages/package/[[org]]/[name]/versions.vue

Lines changed: 82 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -235,10 +235,27 @@ watch(
235235
236236
const showPrereleases = ref(false)
237237
const showDeprecated = ref(false)
238+
const filterOptionsOpen = shallowRef(false)
239+
const filterOptionsRef = useTemplateRef('filterOptionsRef')
240+
const filterOptionsId = useId()
238241
const tagsSortMode = ref<'priority' | 'date'>('priority')
239242
const tagsSortOrder = ref<'asc' | 'desc'>('desc')
240243
const showHiddenTags = ref(false)
241244
245+
const activeFilterOptionsCount = computed(
246+
() => Number(showPrereleases.value) + Number(showDeprecated.value),
247+
)
248+
249+
onClickOutside(filterOptionsRef, () => {
250+
filterOptionsOpen.value = false
251+
})
252+
253+
useEventListener('keydown', event => {
254+
if (event.key === 'Escape' && filterOptionsOpen.value) {
255+
filterOptionsOpen.value = false
256+
}
257+
})
258+
242259
const visibleVersionGroups = computed(() => {
243260
if (showPrereleases.value && showDeprecated.value) return versionGroups.value
244261
return versionGroups.value
@@ -248,7 +265,9 @@ const visibleVersionGroups = computed(() => {
248265
if (!showDeprecated.value && fullVersionMap.value?.get(v)?.deprecated) return false
249266
return true
250267
})
251-
return versions.length === group.versions.length ? group : { ...group, versions }
268+
return versions.length === group.versions.length
269+
? group
270+
: Object.assign({}, group, { versions })
252271
})
253272
.filter(group => group.versions.length > 0)
254273
})
@@ -338,35 +357,74 @@ const flatItems = computed<FlatItem[]>(() => {
338357
<h1 class="text-sm text-fg-muted shrink-0">{{ $t('package.versions.page_title') }}</h1>
339358
</div>
340359
<div class="flex items-center gap-2">
341-
<div
342-
class="flex items-center gap-1"
343-
role="group"
344-
:aria-label="$t('package.versions.filter_controls')"
345-
>
346-
<TooltipApp :text="$t('package.versions.show_prereleases')" position="bottom">
360+
<div ref="filterOptionsRef" class="relative">
361+
<TooltipApp :text="$t('package.versions.filter_controls')" position="bottom">
347362
<button
348363
type="button"
349-
class="inline-flex items-center gap-1.5 px-2 py-1 text-xs font-medium rounded-md border transition-colors cursor-pointer aria-pressed:(bg-fg/10 border-fg/20 text-fg) bg-transparent border-transparent text-fg-muted hover:bg-bg-subtle hover:text-fg"
350-
:aria-pressed="showPrereleases"
351-
:aria-label="$t('package.versions.show_prereleases')"
352-
@click="showPrereleases = !showPrereleases"
364+
class="relative inline-flex items-center justify-center size-8 rounded-md border transition-colors cursor-pointer"
365+
:class="
366+
activeFilterOptionsCount
367+
? 'bg-fg/10 border-fg/20 text-fg'
368+
: 'border-border text-fg-muted hover:bg-bg-subtle hover:text-fg'
369+
"
370+
:aria-label="$t('package.versions.filter_controls')"
371+
:aria-expanded="filterOptionsOpen"
372+
:aria-controls="filterOptionsId"
373+
aria-haspopup="dialog"
374+
@click="filterOptionsOpen = !filterOptionsOpen"
353375
>
354-
<span class="i-lucide:flask-conical w-3.5 h-3.5 shrink-0" aria-hidden="true" />
355-
<span class="hidden sm:inline">{{ $t('package.versions.show_prereleases') }}</span>
376+
<span class="i-lucide:list-filter size-3.5" aria-hidden="true" />
377+
<span
378+
v-if="activeFilterOptionsCount"
379+
class="absolute -top-1 -end-1 min-w-4 h-4 px-1 rounded-full bg-accent text-bg text-[10px] leading-4 font-mono"
380+
aria-hidden="true"
381+
>
382+
{{ activeFilterOptionsCount }}
383+
</span>
356384
</button>
357385
</TooltipApp>
358-
<TooltipApp :text="$t('package.versions.show_deprecated')" position="bottom">
359-
<button
360-
type="button"
361-
class="inline-flex items-center gap-1.5 px-2 py-1 text-xs font-medium rounded-md border transition-colors cursor-pointer aria-pressed:(bg-fg/10 border-fg/20 text-fg) bg-transparent border-transparent text-fg-muted hover:bg-bg-subtle hover:text-fg"
362-
:aria-pressed="showDeprecated"
363-
:aria-label="$t('package.versions.show_deprecated')"
364-
@click="showDeprecated = !showDeprecated"
386+
387+
<Transition
388+
enter-active-class="transition-all duration-150"
389+
leave-active-class="transition-all duration-100"
390+
enter-from-class="opacity-0 translate-y-1"
391+
leave-to-class="opacity-0 translate-y-1"
392+
>
393+
<div
394+
v-if="filterOptionsOpen"
395+
:id="filterOptionsId"
396+
class="absolute end-0 top-full mt-2 z-30 w-52 bg-bg-subtle/80 backdrop-blur-sm border border-border-subtle rounded-lg shadow-lg shadow-bg-elevated/50 overflow-hidden px-1"
397+
role="dialog"
398+
:aria-label="$t('package.versions.filter_controls')"
365399
>
366-
<span class="i-lucide:archive w-3.5 h-3.5 shrink-0" aria-hidden="true" />
367-
<span class="hidden sm:inline">{{ $t('package.versions.show_deprecated') }}</span>
368-
</button>
369-
</TooltipApp>
400+
<div class="py-1">
401+
<label
402+
class="flex gap-2 items-center px-3 py-2 rounded-md hover:bg-fg/10 transition-colors cursor-pointer"
403+
>
404+
<input
405+
v-model="showPrereleases"
406+
type="checkbox"
407+
class="w-4 h-4 accent-fg bg-bg-muted border-border rounded"
408+
/>
409+
<span class="text-sm text-fg font-mono flex-1">
410+
{{ $t('package.versions.show_prereleases') }}
411+
</span>
412+
</label>
413+
<label
414+
class="flex gap-2 items-center px-3 py-2 rounded-md hover:bg-fg/10 transition-colors cursor-pointer"
415+
>
416+
<input
417+
v-model="showDeprecated"
418+
type="checkbox"
419+
class="w-4 h-4 accent-fg bg-bg-muted border-border rounded"
420+
/>
421+
<span class="text-sm text-fg font-mono flex-1">
422+
{{ $t('package.versions.show_deprecated') }}
423+
</span>
424+
</label>
425+
</div>
426+
</div>
427+
</Transition>
370428
</div>
371429
<div class="relative">
372430
<InputBase

0 commit comments

Comments
 (0)