fix(sprint-5/etapa-4h-2): observar prop open en vez de onOpenChange — fix anterior no se disparaba
Some checks failed
/ Deploy to Cloudflare Pages (push) Has been cancelled
Some checks failed
/ Deploy to Cloudflare Pages (push) Has been cancelled
El fix anterior (1aa1486) interceptaba onOpenChange de SheetPrimitive.Root, pero ese
callback solo se dispara cuando RADIX decide cerrar internamente (Escape, overlay,
botón X). Cuando el padre cierra el Sheet cambiando el prop `open` directamente —que
es lo que hace ProfileSheet.handleSave(): llama onOpenChange(false), que es
setProfileOpen(false) del padre AppHeader— Radix nunca invoca su propio onOpenChange.
El wrapper nunca se ejecutaba para este caso, exactamente el que reportó el usuario
en producción (body queda con pointer-events:none stuck tras guardar perfil).
Fix: useEffect que observa el prop `open` en sí, cubre ambos canales de cierre
(interno de Radix y externo del padre) sin depender de qué disparó el cambio.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -6,27 +6,28 @@ import { cn } from '@/lib/utils'
|
||||
|
||||
// Bug conocido de Radix/react-remove-scroll: si un re-render externo coincide con la
|
||||
// animación de cierre, el cleanup que restaura `pointer-events` del body no se ejecuta
|
||||
// — toda la página queda no interactiva hasta refrescar manualmente. El defer de 350ms
|
||||
// en algunos callers (ej. ProfileSheet) mitiga UNA causa, pero no es estructural: este
|
||||
// fallback corrige el estado real del DOM sin asumir cuál fue la causa de la falla.
|
||||
// 400ms > duración de la animación de salida (300ms, ver sheetVariants).
|
||||
function Sheet({ onOpenChange, ...props }: React.ComponentPropsWithoutRef<typeof SheetPrimitive.Root>) {
|
||||
return (
|
||||
<SheetPrimitive.Root
|
||||
onOpenChange={(open) => {
|
||||
onOpenChange?.(open)
|
||||
if (!open) {
|
||||
window.setTimeout(() => {
|
||||
// — toda la página queda no interactiva hasta refrescar manualmente.
|
||||
//
|
||||
// `onOpenChange` de Radix NO es un canal confiable para detectar esto: solo se dispara
|
||||
// cuando RADIX decide cerrar internamente (Escape, click en overlay, botón X). Cuando el
|
||||
// padre cierra el Sheet cambiando el prop `open` directamente (ej. ProfileSheet.handleSave
|
||||
// llama onOpenChange(false), que es setProfileOpen(false) del padre), Radix nunca invoca
|
||||
// su propio onOpenChange — por eso un wrapper de ese callback no detecta este caso.
|
||||
// Observar el prop `open` en sí cubre ambos canales de cierre.
|
||||
function Sheet({ open, ...props }: React.ComponentPropsWithoutRef<typeof SheetPrimitive.Root>) {
|
||||
React.useEffect(() => {
|
||||
if (open) return
|
||||
// 400ms > duración de la animación de salida (300ms, ver sheetVariants).
|
||||
const timeoutId = window.setTimeout(() => {
|
||||
const stillHasOpenDialog = document.querySelector('[role="dialog"][data-state="open"]')
|
||||
if (!stillHasOpenDialog && document.body.style.pointerEvents === 'none') {
|
||||
document.body.style.pointerEvents = ''
|
||||
}
|
||||
}, 400)
|
||||
}
|
||||
}}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
return () => window.clearTimeout(timeoutId)
|
||||
}, [open])
|
||||
|
||||
return <SheetPrimitive.Root open={open} {...props} />
|
||||
}
|
||||
const SheetTrigger = SheetPrimitive.Trigger
|
||||
const SheetClose = SheetPrimitive.Close
|
||||
|
||||
Reference in New Issue
Block a user