@@ -235,10 +235,27 @@ watch(
235235
236236const showPrereleases = ref (false )
237237const showDeprecated = ref (false )
238+ const filterOptionsOpen = shallowRef (false )
239+ const filterOptionsRef = useTemplateRef (' filterOptionsRef' )
240+ const filterOptionsId = useId ()
238241const tagsSortMode = ref <' priority' | ' date' >(' priority' )
239242const tagsSortOrder = ref <' asc' | ' desc' >(' desc' )
240243const 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+
242259const 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