fix(ui): reemplaza panel-debajo-del-listado por DetailPopup de tamaño fijo
El detalle de un item de listado (actividad, departamento, usuario, proyecto nuevo, catalogo) ya no se apila debajo ni al costado del listado: ahora abre en un popup que cubre la ventana, deja el listado inactivo detras, nunca se cierra con clic afuera (solo con el boton Cerrar o una accion explicita del formulario) y mantiene un alto FIJO por instancia para que cambiar de pestaña interna (Info/Subtareas/Dependencias/Comentarios/ Documentos) no reajuste su tamaño. De paso corrige un bug real de stacking: ContentDialog no usaba portal a document.body, así que un dialogo de confirmacion abierto desde dentro de un DetailPopup quedaba oculto detras de este. Ahora ambos son portales con una jerarquia de z-index explicita (Flyout 100 < DetailPopup 200 < ContentDialog 250 < Toast 300). En el detalle de actividad, Subtareas y Dependencias pasan de estar apiladas dentro de la pestaña Info a ser cada una su propia pestaña. Regla documentada en project-md-templates/UI-UX-WINDOWS.md (componente DetailPopup) para que aplique a futuros proyectos de escritorio Windows del grupo. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import { createPortal } from 'react-dom';
|
||||
import { useUi } from '../context/ui-context.jsx';
|
||||
import { Button } from './Button.jsx';
|
||||
|
||||
@@ -17,8 +18,11 @@ export function ContentDialogHost() {
|
||||
if (!action.keepOpen) closeDialog();
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="dialog-overlay" onMouseDown={(e) => { if (e.target === e.currentTarget) closeDialog(); }}>
|
||||
// Regla dura: NUNCA se cierra con clic afuera (a diferencia de Flyout) — solo con un boton.
|
||||
// Portal a document.body (igual que Flyout/DetailPopup): garantiza que quede SIEMPRE por
|
||||
// encima de cualquier DetailPopup abierto, sin depender del punto del arbol donde se monta.
|
||||
return createPortal(
|
||||
<div className="dialog-overlay">
|
||||
<div className="dialog-surface">
|
||||
<div className="dialog-stripe" style={{ background: `rgb(var(--${STRIPE_COLOR[tone]}))` }} />
|
||||
<div className="dialog-body">
|
||||
@@ -33,6 +37,7 @@ export function ContentDialogHost() {
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>,
|
||||
document.body
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
import { createPortal } from 'react-dom';
|
||||
import { X } from 'lucide-react';
|
||||
|
||||
// Popup grande para ver/editar el detalle de un elemento de un listado (reemplaza el patron
|
||||
// "panel debajo del listado"). Reglas duras:
|
||||
// 1. NUNCA se cierra con clic afuera del popup — solo con el boton "Cerrar" de su header o una
|
||||
// accion explicita del formulario (ej. Guardar/Cancelar).
|
||||
// 2. Alto FIJO (no se ajusta al contenido): moverse entre pestañas/secciones internas del popup
|
||||
// (ej. Info/Comentarios/Documentos) nunca debe cambiar su tamaño — solo el contenido interno
|
||||
// hace scroll. `height` es fijo por instancia; ajustar via prop segun cuanto contenido espera.
|
||||
export function DetailPopup({ open, title, onClose, children, width = 720, height = 640 }) {
|
||||
if (!open) return null;
|
||||
return createPortal(
|
||||
<div className="detail-popup-overlay">
|
||||
<div className="detail-popup" style={{ maxWidth: width, height }}>
|
||||
<div className="detail-popup-header">
|
||||
<div className="detail-popup-title">{title}</div>
|
||||
<button className="icon-btn" onClick={onClose}><X /></button>
|
||||
</div>
|
||||
<div className="detail-popup-body">{children}</div>
|
||||
</div>
|
||||
</div>,
|
||||
document.body
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user