Interfaz flotante
Usa @floating-ui/dom para cada elemento interactivo posicionado en relación a un disparador. No calcules coordenadas manualmente ni dependas de desplazamientos absolutos CSS para desplegables, popovers, menús, listas de combobox o tooltips.
Estructura requerida
- Renderiza las superposiciones mediante
createPortal(..., document.body)para que el layout y los contextos de apilamiento no las recorten. - Posiciónalas con
computePositiondentro deautoUpdate; limpia la función devuelta porautoUpdatecuando la superposición se cierre o desmonte. - Parte del control existente más cercano en
apps/desktop/src/components/ui. Coincide con sus middlewaresplacement,offset,flip,shiftysizea menos que la interacción requiera una diferencia deliberada. - Almacena las coordenadas
left,top, el ancho y la altura disponible en estado de React. Aplica el estado a la raíz del portal; no mutes los estilos de los elementos directamente. - Usa
sizecuando el ancho de referencia o la altura del viewport restrinja la superposición. Las listas que pueden crecer deben usarcomponents/virtual/VirtualList.tsx; mantén los encabezados y pies fijos fuera del viewport virtual.
Invariantes de interacción
- Mantén visible el borde de apertura/enfoque del disparador mientras el foco esté dentro de una superposición portaleada.
- Cierra al hacer clic fuera o presionar Escape, luego retorna el foco al disparador.
- Las comprobaciones de clic fuera deben incluir tanto el disparador como la superposición. Una superposición portaleada anidada debe detener su evento de puntero para que no llegue al oyente de clic fuera del padre, de modo que interactuar con un menú hijo nunca cierre su padre.
- Expón el estado del disparador con
aria-expanded,aria-controlsy el correspondientearia-haspopup; asigna a la superposición la semántica adecuada (menu, listbox, dialog o tooltip). - Verifica la colocación cerca de todos los bordes del viewport, clics en superposiciones anidadas, cierre con teclado, desplazamiento virtual y comportamiento de pie fijo.