feature(SearchModal): Auto close the search modal upon route change

Signed-off-by: Renan Mendes Carvalho <aitherios@gmail.com>
This commit is contained in:
Renan Mendes Carvalho
2022-12-21 14:56:19 +01:00
committed by Fredrik Adelöw
parent eb29b3e7b4
commit 9dbdcccd20
3 changed files with 39 additions and 12 deletions
@@ -92,7 +92,7 @@ const useStyles = makeStyles(theme => ({
viewResultsLink: { verticalAlign: '0.5em' },
}));
export const Modal = ({ toggleModal }: SearchModalProps) => {
export const Modal = () => {
const classes = useStyles();
const navigate = useNavigate();
const { transitions } = useTheme();
@@ -107,9 +107,8 @@ export const Modal = ({ toggleModal }: SearchModalProps) => {
});
const handleSearchResultClick = useCallback(() => {
toggleModal();
setTimeout(focusContent, transitions.duration.leavingScreen);
}, [toggleModal, focusContent, transitions]);
}, [focusContent, transitions]);
const handleSearchBarKeyDown = useCallback(
(e: KeyboardEvent<HTMLInputElement | HTMLTextAreaElement>) => {
@@ -188,7 +187,7 @@ export const SearchModal = (props: SearchModalProps) => {
{open && (
<SearchContextProvider inheritParentContextIfAvailable>
{(children && children({ toggleModal })) ?? (
<Modal toggleModal={toggleModal} />
<Modal />
)}
</SearchContextProvider>
)}
@@ -14,7 +14,14 @@
* limitations under the License.
*/
import React, { ReactNode, useCallback, useContext, useState } from 'react';
import React, {
ReactNode,
useCallback,
useContext,
useState,
useEffect,
} from 'react';
import { useLocation } from 'react-router-dom';
import {
createVersionedContext,
createVersionedValueMap,
@@ -96,7 +103,8 @@ export const SearchModalProvider = (props: SearchModalProviderProps) => {
/**
* Use this hook to manage the state of {@link SearchModal}
* and change its visibility.
* and change its visibility. Monitors route changes setting the hidden state
* to avoid having to call toggleModal on every result click.
*
* @public
*
@@ -105,10 +113,6 @@ export const SearchModalProvider = (props: SearchModalProviderProps) => {
* functions for changing the visibility of the modal.
*/
export function useSearchModal(initialState = false) {
// Check for any existing parent context.
const parentContext = useContext(SearchModalContext);
const parentContextValue = parentContext?.atVersion(1);
const [state, setState] = useState({
hidden: !initialState,
open: initialState,
@@ -132,8 +136,32 @@ export function useSearchModal(initialState = false) {
[],
);
// Check for any existing parent context.
const parentContext = useContext(SearchModalContext);
const parentContextValue = parentContext?.atVersion(1);
const isParentContextPresent = !!parentContextValue?.state;
// Monitor route pathname changes to automatically hide the modal.
const { pathname } = useLocation();
const [openedPathname, setOpenedPathname] = useState<string | null>(null);
const { open, hidden } = state;
const isModalOpened = !isParentContextPresent && open && !hidden;
useEffect(() => {
if (isModalOpened) {
setOpenedPathname(pathname);
}
}, [isModalOpened, pathname]);
useEffect(() => {
if (isModalOpened && openedPathname && openedPathname !== pathname) {
setState(prevState => ({
open: prevState.open,
hidden: true,
}));
}
}, [isModalOpened, openedPathname, pathname]);
// Inherit from parent context, if set.
return parentContextValue?.state
return isParentContextPresent
? parentContextValue
: { state, toggleModal, setOpen };
}