fix: smooth mobile edit transition and align modal validation behavior (#286)

* fix: reliable Escape key close for all modals via useEscapeKey hook

- Add useEscapeKey hook (document-level keydown listener)
- Retrofit all 12 modal/overlay components to use it
- Remove redundant overlay onKeyDown Escape handlers
- Simplify modal-content onKeyDown to plain stopPropagation
- Replace MedDetailModal's capture-phase useEffect with 3 useEscapeKey calls
- Replace SharedSchedule's inline useEffect with useEscapeKey
- Add mandatory modal rules to UI Consistency skill
- All 777 frontend + 569 backend tests pass

* fix: smooth mobile edit transition and align modal validation behavior

* fix: keep overlay keydown non-closing for Enter key

* fix: show mobile name error when validation already exists

* fix: restore app-level escape priority handling

* fix: prioritize schedule lightbox on Escape
This commit is contained in:
Daniel Volz
2026-02-23 06:42:06 +01:00
committed by GitHub
parent 2aa6b1f406
commit ba36f67371
21 changed files with 337 additions and 163 deletions
+7 -13
View File
@@ -2,7 +2,8 @@
// ConfirmModal Component - Simple confirmation dialog
// =============================================================================
import { type ReactNode, useEffect } from "react";
import type { ReactNode } from "react";
import { useEscapeKey } from "../hooks/useEscapeKey";
export interface ConfirmModalProps {
title: string;
@@ -27,29 +28,22 @@ export function ConfirmModal({
confirmVariant = "primary",
overlayClassName,
}: ConfirmModalProps) {
// Close on Escape key
useEffect(() => {
function handleKeyDown(e: KeyboardEvent) {
if (e.key === "Escape") {
onCancel();
}
}
document.addEventListener("keydown", handleKeyDown);
return () => document.removeEventListener("keydown", handleKeyDown);
}, [onCancel]);
useEscapeKey(true, onCancel);
return (
<div
className={`modal-overlay${overlayClassName ? ` ${overlayClassName}` : ""}`}
onClick={onCancel}
onKeyDown={(e) => {
if (e.key === "Escape") onCancel();
if (e.key !== "Escape") e.stopPropagation();
}}
>
<div
className="modal-content confirm-modal"
onClick={(e) => e.stopPropagation()}
onKeyDown={(e) => e.stopPropagation()}
onKeyDown={(e) => {
if (e.key !== "Escape") e.stopPropagation();
}}
style={{ maxWidth: "450px" }}
>
<button className="modal-close" onClick={onCancel}>