diff --git a/client-app/pages/product.vue b/client-app/pages/product.vue index 1db216c8d5..1af07eff77 100644 --- a/client-app/pages/product.vue +++ b/client-app/pages/product.vue @@ -235,7 +235,7 @@ const { isFiltersSidebarVisible, productsFilters, applyFilters: _applyFilters, - hideFiltersSidebar, + hideFiltersSidebar: _hideFiltersSidebar, resetFacetFilters: _resetFacetFilters, showFiltersSidebar, } = useProducts({ @@ -403,6 +403,14 @@ async function resetFacetFilters(): Promise { void applyFilters(productsFilters.value); } +function hideFiltersSidebar(): void { + _hideFiltersSidebar(); + const variationsFiltersButton = document.getElementById(`${productId.value}-variations-filters-button`); + if (variationsFiltersButton) { + variationsFiltersButton.focus(); + } +} + function checkLineItemId() { const cartItems = cart.value?.items; return cartItems?.some((item) => item.id === lineItemId); diff --git a/client-app/shared/catalog/components/category/filters-popup-sidebar.vue b/client-app/shared/catalog/components/category/filters-popup-sidebar.vue index 0bb651f843..c3af5dcfeb 100644 --- a/client-app/shared/catalog/components/category/filters-popup-sidebar.vue +++ b/client-app/shared/catalog/components/category/filters-popup-sidebar.vue @@ -7,6 +7,7 @@ > import cloneDeep from "lodash/cloneDeep"; import isEqual from "lodash/isEqual"; -import { watch, ref, computed } from "vue"; +import { watch, ref, computed, nextTick, onMounted, onUnmounted } from "vue"; import { usePurchasedBefore } from "@/shared/catalog/composables"; import { useModal } from "@/shared/modal"; +import { useComponentId } from "@/ui-kit/composables"; import type { SearchProductFilterResult } from "@/core/api/graphql/types.ts"; import type { ProductsFiltersType } from "@/shared/catalog"; import ProductsFilters from "@/shared/catalog/components/products-filters.vue"; @@ -124,6 +126,8 @@ interface IProps { isExistSelectedFacets: boolean; } +const productsFiltersId = useComponentId("products-filters"); + const localFilters = ref({ filters: [], facets: [], @@ -159,9 +163,11 @@ watch( watch( () => props.isVisible, - (visible) => { + async (visible) => { if (visible) { beforeChangeFilterState.value = cloneDeep(props.popupSidebarFilters); + await nextTick(); + focusFirstElement(); } }, ); @@ -196,6 +202,22 @@ function onApply() { emit("hidePopupSidebar"); } +function focusFirstElement() { + const firstFocusableElement = document + .getElementById(productsFiltersId) + ?.querySelector("input:not(:disabled), button:not(:disabled)"); + if (firstFocusableElement && firstFocusableElement instanceof HTMLElement) { + firstFocusableElement.focus(); + } +} + +function handleKeydown(event: KeyboardEvent) { + if (event.key === "Escape" && props.isVisible) { + event.preventDefault(); + emit("hidePopupSidebar"); + } +} + const { openModal } = useModal(); function openBranchesModal() { openModal({ @@ -213,6 +235,14 @@ function openBranchesModal() { }, }); } + +onMounted(() => { + document.addEventListener("keydown", handleKeydown); +}); + +onUnmounted(() => { + document.removeEventListener("keydown", handleKeydown); +});