Skip to content
This repository has been archived by the owner on Feb 22, 2023. It is now read-only.

Commit

Permalink
Move the sidebar in the DOM order (#2185)
Browse files Browse the repository at this point in the history
* Make the sidebar appear after the header in the DOM

* Add e2e test
  • Loading branch information
obulat authored Feb 15, 2023
1 parent 68fbe32 commit 3baca4c
Show file tree
Hide file tree
Showing 12 changed files with 119 additions and 217 deletions.
18 changes: 1 addition & 17 deletions src/components/VAllResultsGrid/VAllResultsGrid.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,12 @@
class="results-grid mb-4 grid grid-cols-2 gap-4 lg:grid-cols-5 2xl:grid-cols-6"
>
<VContentLink
v-for="([mediaType, count], i) in resultCounts"
v-for="[mediaType, count] in resultCounts"
:key="mediaType"
:media-type="mediaType"
:results-count="count"
:to="contentLinkPath(mediaType)"
class="lg:col-span-2"
@shift-tab="handleShiftTab($event, i)"
/>
</div>
<VSnackbar size="large" :is-visible="isSnackbarVisible">
Expand Down Expand Up @@ -58,11 +57,8 @@ import { useMediaStore } from "~/stores/media"
import { useSearchStore } from "~/stores/search"
import { useUiStore } from "~/stores/ui"
import { useFocusFilters } from "~/composables/use-focus-filters"
import { useI18n } from "~/composables/use-i18n"
import { Focus } from "~/utils/focus-management"
import VSnackbar from "~/components/VSnackbar.vue"
import VImageCellSquare from "~/components/VAllResultsGrid/VImageCellSquare.vue"
import VAudioCell from "~/components/VAllResultsGrid/VAudioCell.vue"
Expand Down Expand Up @@ -112,17 +108,6 @@ export default defineComponent({
const noResults = computed(
() => fetchState.value.isFinished && allMedia.value.length === 0
)
const focusFilters = useFocusFilters()
/**
* Move focus to the filters sidebar if shift-tab is pressed on the first content link.
* @param i - the index of the content link.
* @param event - keydown event
*/
const handleShiftTab = (event: KeyboardEvent, i: number) => {
if (i === 0) {
focusFilters.focusFilterSidebar(event, Focus.Last)
}
}
const uiStore = useUiStore()
const isSnackbarVisible = computed(() => uiStore.areInstructionsVisible)
Expand All @@ -142,7 +127,6 @@ export default defineComponent({
resultsLoading,
resultCounts,
noResults,
handleShiftTab,
contentLinkPath,
Expand Down
17 changes: 0 additions & 17 deletions src/components/VExternalSearch/VExternalSearchForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
ref="sectionRef"
class="external-sources flex flex-row place-items-center justify-center py-4"
data-testid="external-sources-form"
@keydown.tab.exact="handleTab"
>
<i18n
v-if="!hasNoResults && isSupported"
Expand Down Expand Up @@ -95,7 +94,6 @@ import {
SetupContext,
} from "@nuxtjs/composition-api"
import { getFocusableElements } from "~/utils/focus-management"
import { defineEvent } from "~/types/emits"
import { useUiStore } from "~/stores/ui"
Expand Down Expand Up @@ -172,25 +170,10 @@ export default defineComponent({
emit: emit as SetupContext["emit"],
})
/**
* Find the last focusable element in VSearchGridFilter to add a 'Tab' keydown event
* handler to it.
*/
const lastFocusableElement = computed<HTMLElement>(() => {
const focusable = getFocusableElements(sectionRef.value)
return focusable[focusable.length - 1]
})
const handleTab = (event: KeyboardEvent) => {
if (event.target === lastFocusableElement.value) {
emit("tab", event)
}
}
return {
sectionRef,
triggerRef,
triggerElement,
handleTab,
isMd,
closeDialog,
Expand Down
68 changes: 2 additions & 66 deletions src/components/VFilters/VSearchGridFilter.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,11 @@
variant="plain"
class="label-bold absolute py-1 px-4 text-pink end-0 hover:ring hover:ring-pink"
@click="clearFilters"
@keydown.shift.tab.exact="focusFilterButton"
>
{{ $t("filter-list.clear") }}
</VButton>
</header>
<form
ref="filtersFormRef"
class="filters-form"
@keydown.tab.exact="handleTabKey"
@keydown.shift.tab.exact="handleShiftTabKey"
>
<form ref="filtersFormRef" class="filters-form">
<VFilterChecklist
v-for="filterType in filterTypes"
:key="filterType"
Expand Down Expand Up @@ -58,9 +52,7 @@ import { watchDebounced } from "@vueuse/core"
import { useSearchStore } from "~/stores/search"
import { areQueriesEqual, ApiQueryParams } from "~/utils/search-query-transform"
import { Focus, focusIn, getFocusableElements } from "~/utils/focus-management"
import type { NonMatureFilterCategory } from "~/constants/filters"
import { useFocusFilters } from "~/composables/use-focus-filters"
import { defineEvent } from "~/types/emits"
import VFilterChecklist from "~/components/VFilters/VFilterChecklist.vue"
Expand Down Expand Up @@ -94,7 +86,7 @@ export default defineComponent({
emits: {
close: defineEvent(),
},
setup(props) {
setup() {
const searchStore = useSearchStore()
const { i18n } = useContext()
Expand Down Expand Up @@ -124,70 +116,14 @@ export default defineComponent({
{ debounce: 800, maxWait: 5000 }
)
const focusableElements = computed(() =>
getFocusableElements(filtersFormRef.value)
)
/**
* Find the last focusable element in VSearchGridFilter to add a 'Tab' keydown event
* handler to it.
* We could actually hard-code this because 'searchBy' is always the last now.
*/
const lastFocusableElement = computed<HTMLElement>(() => {
return focusableElements.value[focusableElements.value.length - 1]
})
/**
* We add the `Shift-Tab` handler to the first focusable checkbox so that focus can go back
* to the filter button
*/
const firstFocusableElement = computed<HTMLElement | undefined>(
() => focusableElements.value[0]
)
/**
* When the user presses 'Tab' on the last focusable element, we need to
* move focus to the first focusable element in main.
* @param event
*/
const handleTabKey = (event: KeyboardEvent) => {
if (!props.changeTabOrder) return
if (lastFocusableElement.value === event.target) {
event.preventDefault()
focusIn(document.querySelector("main"), Focus.First)
}
}
/**
* Move focus to the filter button only when this checkbox is the first focusable
* element in the search grid filter, i.e. the 'Clear filters' button is hidden.
* @param event - The keydown event
*/
const handleShiftTabKey = (event: KeyboardEvent) => {
if (!props.changeTabOrder) return
if (
firstFocusableElement.value === event.target &&
!isAnyFilterApplied.value
) {
focusFilterButton(event)
}
}
const focusFilters = useFocusFilters()
const focusFilterButton = (event?: KeyboardEvent) => {
focusFilters.focusFilterButton(event)
}
return {
firstFocusableElement,
filtersFormRef,
isAnyFilterApplied,
filters,
filterTypes,
filterTypeTitle,
clearFilters: searchStore.clearFilters,
toggleFilter: searchStore.toggleFilter,
handleTabKey,
handleShiftTabKey,
focusFilterButton,
}
},
})
Expand Down
13 changes: 0 additions & 13 deletions src/components/VHeader/VHeaderDesktop.vue
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@
aria-haspopup="dialog"
:aria-expanded="isSidebarVisible"
@toggle="toggleSidebar"
@tab="onTab"
/>
</header>
</template>
Expand All @@ -55,10 +54,8 @@ import { useUiStore } from "~/stores/ui"
import { IsHeaderScrolledKey, IsSidebarVisibleKey } from "~/types/provides"
import { useFocusFilters } from "~/composables/use-focus-filters"
import { useSearch } from "~/composables/use-search"
import { Focus } from "~/utils/focus-management"
import { ensureFocus } from "~/utils/reakit-utils/focus"
import VFilterButton from "~/components/VHeader/VFilterButton.vue"
Expand Down Expand Up @@ -113,15 +110,6 @@ export default defineComponent({
const toggleSidebar = () => uiStore.toggleFilters()
const focusFilters = useFocusFilters()
/**
* Focus the first element in the sidebar when navigating from the VFilterButton
* using keyboard `Tab` key.
*/
const onTab = (event: KeyboardEvent) => {
focusFilters.focusFilterSidebar(event, Focus.First)
}
const isXl = computed(() => uiStore.isBreakpoint("xl"))
return {
Expand All @@ -140,7 +128,6 @@ export default defineComponent({
searchStatus,
searchTerm,
toggleSidebar,
onTab,
}
},
})
Expand Down
19 changes: 3 additions & 16 deletions src/components/VImageGrid/VImageGrid.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@
<section>
<div class="image-grid flex flex-wrap gap-4">
<VImageCell
v-for="(image, index) in images"
v-for="image in images"
:key="image.id"
:image="image"
:search-term="searchTerm"
@shift-tab="handleShiftTab($event, index)"
/>
</div>
<h5 v-if="isError && !fetchState.isFinished" class="py-4">
Expand All @@ -33,8 +32,6 @@ import { useSearchStore } from "~/stores/search"
import type { FetchState } from "~/types/fetch-state"
import type { ImageDetail } from "~/types/media"
import { defineEvent } from "~/types/emits"
import VLoadMore from "~/components/VLoadMore.vue"
import VImageCell from "~/components/VImageGrid/VImageCell.vue"
Expand All @@ -61,23 +58,13 @@ export default defineComponent({
required: true,
},
},
emits: {
"shift-tab": defineEvent(),
},
setup(props, { emit }) {
setup(props) {
const searchStore = useSearchStore()
const searchTerm = computed(() => searchStore.searchTerm)
const isError = computed(() => Boolean(props.fetchState.fetchingError))
const handleShiftTab = (event: KeyboardEvent, index: number) => {
if (index === 0) {
event.preventDefault()
emit("shift-tab")
}
}
return { isError, handleShiftTab, searchTerm }
return { isError, searchTerm }
},
})
</script>
Expand Down
29 changes: 0 additions & 29 deletions src/composables/use-focus-filters.ts

This file was deleted.

Loading

0 comments on commit 3baca4c

Please sign in to comment.