feat: close modals with browser back button on mobile (#257)

* feat: close modals with browser back button on mobile

Create reusable useModalHistory hook that pushes history state when a
modal opens and listens for popstate to close it. Apply to ReportModal,
ClearMissedConfirm, ExportModal, ImportConfirm, and all modals using
ConfirmModal/ShareDialog/Auth/ExportModal base components. Escape key
handling was already in place for desktop.

Closes #253

* fix: update tests for renamed button labels and missing useModalHistory mock
This commit is contained in:
Daniel Volz
2026-02-21 18:00:12 +01:00
committed by GitHub
parent 94bd8bd6e8
commit 943148fb49
15 changed files with 88 additions and 11 deletions
+1
View File
@@ -8,6 +8,7 @@ export type { UseMedicationFormReturn } from "./useMedicationForm";
export { defaultBlister, defaultForm, useMedicationForm } from "./useMedicationForm";
export type { UseMedicationsReturn } from "./useMedications";
export { useMedications } from "./useMedications";
export { useModalHistory } from "./useModalHistory";
export type { UseRefillReturn } from "./useRefill";
export { useRefill } from "./useRefill";
export type { Settings, UseSettingsReturn } from "./useSettings";
+32
View File
@@ -0,0 +1,32 @@
import { useEffect, useRef } from "react";
/**
* Push a history entry when a modal opens so the browser back button closes it.
* On popstate (back), calls `onClose` to dismiss the modal.
*/
export function useModalHistory(isOpen: boolean, modalKey: string, onClose: () => void) {
const pushedRef = useRef(false);
useEffect(() => {
if (isOpen) {
window.history.pushState({ modal: modalKey }, "");
pushedRef.current = true;
} else if (pushedRef.current) {
pushedRef.current = false;
}
}, [isOpen, modalKey]);
useEffect(() => {
if (!isOpen) return;
const handlePopState = () => {
if (pushedRef.current) {
pushedRef.current = false;
onClose();
}
};
window.addEventListener("popstate", handlePopState);
return () => window.removeEventListener("popstate", handlePopState);
}, [isOpen, onClose]);
}