fix(modal): proper mobile bottom sheet — sticky header/footer, scrollable body

- rounded-t-2xl on mobile, full-width (no side padding)
- maxHeight = 100dvh - safe-area-top - 68px nav - safe-area-bottom
- header and footer flex-shrink-0, body flex-1 overflow-y-auto overflow-x-hidden
- save buttons in pinned footer, larger touch targets (py-3, rounded-xl)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-13 19:02:23 +02:00
parent 493f6ab7fc
commit 142d27e85c
+15 -10
View File
@@ -338,12 +338,15 @@ export function EventModal({ type, babyId, onClose, onSaved, initialEvent }: Pro
const segmentInactive = "border-slate-200 dark:border-slate-600 text-slate-500 dark:text-slate-400 hover:border-slate-300"; const segmentInactive = "border-slate-200 dark:border-slate-600 text-slate-500 dark:text-slate-400 hover:border-slate-300";
return ( return (
<div className="fixed inset-0 z-50 flex items-end sm:items-center justify-center p-4 pb-[calc(1rem+env(safe-area-inset-bottom)+64px)] sm:pb-4"> <div className="fixed inset-0 z-50 flex items-end sm:items-center justify-center sm:p-4">
<div className="absolute inset-0 bg-black/30 backdrop-blur-sm" onClick={onClose} /> <div className="absolute inset-0 bg-black/30 backdrop-blur-sm" onClick={onClose} />
<div className="relative w-full max-w-md bg-white dark:bg-slate-800 rounded-2xl shadow-2xl z-10 max-h-[75vh] sm:max-h-[92vh] overflow-y-auto"> <div
{/* Header */} className="relative w-full sm:max-w-md bg-white dark:bg-slate-800 rounded-t-2xl sm:rounded-2xl shadow-2xl z-10 flex flex-col overflow-hidden"
<div className="flex items-center justify-between px-5 py-4 border-b border-slate-100 dark:border-slate-700"> style={{ maxHeight: "calc(100dvh - env(safe-area-inset-top, 0px) - 68px - env(safe-area-inset-bottom, 0px))" }}
>
{/* Header — sticky */}
<div className="flex-shrink-0 flex items-center justify-between px-5 py-4 border-b border-slate-100 dark:border-slate-700">
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<div className={`w-9 h-9 rounded-xl ${config.bgClass} flex items-center justify-center`}> <div className={`w-9 h-9 rounded-xl ${config.bgClass} flex items-center justify-center`}>
<EventIcon name={config.icon} className={`w-5 h-5 ${config.colorClass}`} /> <EventIcon name={config.icon} className={`w-5 h-5 ${config.colorClass}`} />
@@ -357,7 +360,8 @@ export function EventModal({ type, babyId, onClose, onSaved, initialEvent }: Pro
</button> </button>
</div> </div>
<div className="px-5 py-4 space-y-4"> {/* Scrollable body */}
<div className="flex-1 overflow-y-auto overflow-x-hidden px-5 py-4 space-y-4">
{/* Timer */} {/* Timer */}
{config.hasTimer && ( {config.hasTimer && (
<div className="bg-slate-50 dark:bg-slate-700/50 rounded-xl p-4 text-center"> <div className="bg-slate-50 dark:bg-slate-700/50 rounded-xl p-4 text-center">
@@ -756,19 +760,20 @@ export function EventModal({ type, babyId, onClose, onSaved, initialEvent }: Pro
</div> </div>
)} )}
{/* Actions */} </div>
<div className="flex gap-2 pt-1 pb-1">
{/* Footer — sticky */}
<div className="flex-shrink-0 flex gap-2 px-5 py-4 border-t border-slate-100 dark:border-slate-700 bg-white dark:bg-slate-800">
<button type="button" onClick={onClose} <button type="button" onClick={onClose}
className="flex-1 py-2.5 rounded-lg border border-slate-200 dark:border-slate-600 text-slate-600 dark:text-slate-300 text-sm font-medium hover:bg-slate-50 dark:hover:bg-slate-700 transition"> className="flex-1 py-3 rounded-xl border border-slate-200 dark:border-slate-600 text-slate-600 dark:text-slate-300 text-sm font-medium hover:bg-slate-50 dark:hover:bg-slate-700 transition">
Annuler Annuler
</button> </button>
<button type="button" onClick={handleSave} disabled={loading} <button type="button" onClick={handleSave} disabled={loading}
className="flex-[2] py-2.5 rounded-lg bg-indigo-600 hover:bg-indigo-700 disabled:bg-indigo-300 text-white text-sm font-medium transition"> className="flex-[2] py-3 rounded-xl bg-indigo-600 hover:bg-indigo-700 disabled:bg-indigo-300 text-white text-sm font-medium transition">
{loading ? "..." : isEditing ? "Mettre à jour" : "Enregistrer"} {loading ? "..." : isEditing ? "Mettre à jour" : "Enregistrer"}
</button> </button>
</div> </div>
</div> </div>
</div> </div>
</div>
); );
} }