add ability to use browser back button to close MobilePage

This commit is contained in:
Josh Hawkins 2025-04-13 12:31:58 -05:00
parent 10c730501a
commit ce54175430

View File

@ -1,4 +1,10 @@
import { createContext, useContext, useEffect, useState } from "react";
import {
createContext,
useContext,
useEffect,
useState,
useCallback,
} from "react";
import { createPortal } from "react-dom";
import { motion, AnimatePresence } from "framer-motion";
import { IoMdArrowRoundBack } from "react-icons/io";
@ -6,6 +12,7 @@ import { cn } from "@/lib/utils";
import { isPWA } from "@/utils/isPWA";
import { Button } from "@/components/ui/button";
import { useTranslation } from "react-i18next";
import { useLocation } from "react-router-dom";
const MobilePageContext = createContext<{
open: boolean;
@ -24,15 +31,47 @@ export function MobilePage({
onOpenChange,
}: MobilePageProps) {
const [uncontrolledOpen, setUncontrolledOpen] = useState(false);
const location = useLocation();
const open = controlledOpen ?? uncontrolledOpen;
const setOpen = (value: boolean) => {
if (onOpenChange) {
onOpenChange(value);
} else {
setUncontrolledOpen(value);
const setOpen = useCallback(
(value: boolean) => {
if (onOpenChange) {
onOpenChange(value);
} else {
setUncontrolledOpen(value);
}
},
[onOpenChange, setUncontrolledOpen],
);
useEffect(() => {
let isActive = true;
if (open && isActive) {
window.history.pushState({ isMobilePage: true }, "", location.pathname);
}
};
const handlePopState = (event: PopStateEvent) => {
if (open && isActive) {
event.preventDefault();
setOpen(false);
// Delay replaceState to ensure state updates are processed
setTimeout(() => {
if (isActive) {
window.history.replaceState(null, "", location.pathname);
}
}, 0);
}
};
window.addEventListener("popstate", handlePopState);
return () => {
isActive = false;
window.removeEventListener("popstate", handlePopState);
};
}, [open, setOpen, location.pathname]);
return (
<MobilePageContext.Provider value={{ open, onOpenChange: setOpen }}>