ba36f67371
* 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
49 lines
1.1 KiB
TypeScript
49 lines
1.1 KiB
TypeScript
// =============================================================================
|
||
// Lightbox Component - Full-screen image viewer
|
||
// =============================================================================
|
||
|
||
import type { MouseEvent } from "react";
|
||
import { useEscapeKey } from "../hooks/useEscapeKey";
|
||
|
||
export interface LightboxProps {
|
||
src: string;
|
||
alt: string;
|
||
onClose: () => void;
|
||
}
|
||
|
||
export function Lightbox({ src, alt, onClose }: LightboxProps) {
|
||
useEscapeKey(true, onClose);
|
||
|
||
function handleOverlayClick(e: MouseEvent) {
|
||
e.stopPropagation();
|
||
if (e.target === e.currentTarget) {
|
||
onClose();
|
||
}
|
||
}
|
||
|
||
return (
|
||
<div
|
||
className="lightbox-overlay"
|
||
onClick={handleOverlayClick}
|
||
onKeyDown={(e) => {
|
||
if (e.key !== "Escape") e.stopPropagation();
|
||
}}
|
||
>
|
||
<div className="lightbox-container">
|
||
<button className="lightbox-close" onClick={onClose}>
|
||
×
|
||
</button>
|
||
<img
|
||
src={src}
|
||
alt={alt}
|
||
className="lightbox-image"
|
||
onClick={(e) => e.stopPropagation()}
|
||
onKeyDown={(e) => {
|
||
if (e.key !== "Escape") e.stopPropagation();
|
||
}}
|
||
/>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|