2 puntos por GN⁺ 2024-05-11 | 1 comentarios | Compartir por WhatsApp
  • Se puede crear una UI de popover que aparece sobre la página usando solo funciones nativas del navegador, lo que permite implementar patrones como menús, sugerencias y notificaciones de forma más consistente
  • Los popovers de la Popover API siempre son no modales, por lo que para interfaces que deben bloquear la interacción con la página es más adecuado ``
  • Los toggles simples se manejan con atributos HTML como popover, popovertarget y popovertargetaction, y, si hace falta, el estado de visualización se controla con métodos de JavaScript
  • Con ::backdrop, :popover-open, beforetoggle, toggle, etc., se pueden manejar estilos y cambios de estado, y los interest invokers admiten visualización por hover/focus sin JavaScript
  • Es una función Baseline 2025 que funciona en dispositivos y navegadores modernos desde enero de 2025, pero es necesario verificar la compatibilidad en entornos antiguos o con algunas funciones específicas

Qué problema resuelve la Popover API

  • La Popover API proporciona un mecanismo estándar para mostrar contenido de popover sobre otro contenido de la página
  • Los popovers pueden controlarse solo con atributos HTML, o bien se puede manejar directamente su estado de mostrar/ocultar con la API de JavaScript
  • Permite implementar de forma más consistente, con funciones nativas del navegador, patrones de UI que en la web se conocían como overlays, popups, popovers, dialogs, etc.

Si necesitas un modal, usa ``

  • Las interfaces de popover se dividen principalmente en modales y no modales
    • En un modal, no se puede interactuar con el resto de la página mientras el popover está visible
    • En uno no modal, se puede seguir interactuando con el resto de la página aunque el popover esté abierto
  • Los popovers creados con la Popover API siempre son no modales
  • Si necesitas un popover modal que bloquee la interacción con la página, el elemento `` es el adecuado
  • También es válido aplicar popover a como en, lo que permite usar a la vez el control de popover y la semántica de dialog

Uso básico

  • La Popover API puede usarse con frecuencia en interfaces que requieren interacción del usuario
    • Menús de acciones
    • Notificaciones toast personalizadas
    • Sugerencias en elementos de formulario
    • Selectores de contenido
    • UI educativa
  • Con solo HTML se puede crear un botón simple para alternar un popover
Toggle the popover
Popover content

  • En JavaScript, HTMLElement.togglePopover() alterna el estado de mostrar/ocultar del popover
  • La API también ofrece eventos para reaccionar a los cambios de estado del popover y funciones CSS que ayudan con el estilizado

Atributos HTML

  • interestfor
    • Define elementos HTML , , o un elemento SVG como interest invoker
    • El valor es el id del elemento de destino, y ese elemento se ve afectado cuando aparece o desaparece el interest en el elemento invoker
  • popover
    • Es un atributo global que convierte un elemento en un elemento popover
    • Puede recibir como valor los estados "auto", "hint" o "manual"
  • popovertarget
    • Convierte un elemento o en un botón de control del popover
    • El valor es el ID del elemento popover que se controlará
  • popovertargetaction
    • Especifica la acción que el botón de control realizará sobre el popover
    • Los valores posibles son "hide", "show" y "toggle"

Manejar el estado de visualización con CSS

  • ::backdrop
    • Es un pseudoelemento de pantalla completa ubicado justo detrás del elemento popover
    • Si hace falta, puede aplicar efectos como desenfoque al contenido de la página detrás del popover
  • interest-delay, interest-delay-start, interest-delay-end
    • Agregan un tiempo de retraso entre el momento en que el usuario muestra o pierde el interest y el momento en que el navegador reacciona
  • :interest-source, :interest-target
    • Permiten aplicar estilos, respectivamente, al invoker y al elemento de destino vinculado mientras el interest está visible
  • :popover-open
    • Es una pseudoclase que solo coincide cuando el elemento popover está visible
    • Se usa para estilizar el popover en estado abierto

Interfaces de JavaScript y extensiones del DOM

  • InterestEvent
    • Es el objeto de evento de los eventos interest y loseinterest
    • Incluye la propiedad source, que contiene una referencia al elemento interest invoker vinculado
  • ToggleEvent
    • Representa el evento que se dispara cuando un elemento popover alterna entre los estados visible y oculto
    • Es el objeto de evento de los eventos beforetoggle y toggle
  • interestForElement
    • Obtiene o establece la referencia al elemento que el interest invoker tiene como destino
    • Puede usarse en HTMLButtonElement, HTMLAnchorElement, HTMLAreaElement y SVGAElement
  • HTMLElement.popover
    • Obtiene o establece mediante JavaScript el estado popover de un elemento
    • Usa los valores "auto", "hint" y "manual", y también se utiliza para detección de funciones
    • Refleja el valor del atributo global HTML popover
  • popoverTargetElement
    • En HTMLButtonElement y HTMLInputElement, obtiene o establece el elemento popover que controla el botón de control
    • Es la contraparte en JavaScript del atributo HTML popovertarget
  • popoverTargetAction
    • En HTMLButtonElement y HTMLInputElement, obtiene o establece la acción de popover que se realizará
    • Usa los valores "hide", "show" y "toggle", y refleja el atributo popovertargetaction

Métodos y eventos

  • HTMLElement.hidePopover()
    • Elimina el elemento popover del top layer y lo oculta aplicándole estilo display: none
  • HTMLElement.showPopover()
    • Muestra el elemento popover agregándolo al top layer
  • HTMLElement.togglePopover()
    • Alterna el elemento popover entre los estados visible y oculto
  • beforetoggle
    • Se dispara justo antes de que el estado del elemento popover cambie entre visible y oculto
    • Puede usarse para impedir que el popover se abra o para actualizar otros elementos según el estado del popover
  • toggle
    • Se dispara justo después de que cambia el estado del elemento popover
  • interest
    • Se dispara cuando aparece el interest en el elemento de destino del interest invoker
  • loseinterest
    • Se dispara cuando desaparece el interest en el elemento de destino del interest invoker

Ejemplos y enlaces a especificaciones

1 comentarios

 
GN⁺ 2024-05-11
Opiniones en Hacker News
  • La Popover API parece que va a generar un cambio enorme cuando también llegue CSS Anchor Positioning (posicionamiento con anclas en CSS).
    El posicionamiento con anclas permite colocar un elemento en relación con otro elemento de la página.
    Combinado con la Popover API, permite implementar de forma declarativa tooltips personalizados o menús contextuales, y ya no harían falta bibliotecas como PopperJS.
    https://developer.chrome.com/blog/tether-elements-to-each-ot...
    https://popper.js.org/docs/v2/

    • Acabo de publicar un nuevo artículo sobre cómo usar la CSS Anchor API, y está previsto que llegue a Chromium la próxima semana.
      https://developer.chrome.com/blog/anchor-positioning-api
    • El estado de soporte en navegadores se puede ver aquí:
      https://caniuse.com/css-anchor-positioning
    • Si hubiéramos tenido CSS Anchor Positioning durante los últimos años, parece que nos habríamos ahorrado una cantidad enorme de tiempo.
    • Esta es la pieza clave que faltaba.
      La semana pasada intenté crear y desplegar algo con la nueva Popover API, pero la falta de soporte de posicionamiento en todos los navegadores limitó mucho los casos de uso.
      Parece que Firefox, el último navegador que faltaba, ya incorporó el posicionamiento con anclas en la beta, así que no debería tardar demasiado.
    • Sorprende que en 2024 HTML/CSS no tenga un atributo de tooltip como title.
  • Si necesitas un cuadro de diálogo modal, también existe el elemento <dialog>.
    https://developer.mozilla.org/en-US/docs/Web/HTML/Element/di...

    • Si necesitas contenido expandible/plegable, o incluso forzándolo un poco para un “dropdown”, puedes usar <details>.
      Curiosamente, a diferencia de <dialog> o <details>, parece que <popover> no puede ponerse en estado open de forma declarativa solo con un atributo.
      Se siente como una función faltante, y espero que haya habido una razón para esa decisión.
      https://developer.mozilla.org/en-US/docs/Web/HTML/Element/de...
    • Advertiría que llevar las animaciones y el comportamiento modal habitual al nivel que se espera hoy requiere bastante trabajo.
      Es totalmente posible, pero de ninguna manera es algo trivial.
    • Como se señaló, las animaciones son más difíciles, pero viene con accesibilidad, cierre con la tecla Esc, fondo integrado y focus trap integrado.
      El soporte en Safari tardó, pero ahora se puede usar en todas partes.
      Me parece mejor que armarlo combinando etiquetas manualmente.
    • Los primeros párrafos del artículo ya cubren esto.
  • Si se implementa junto con el sistema de ventanas del sistema operativo anfitrión, esta funcionalidad claramente parece necesaria.
    Esto se debe a que, hoy, los popovers siempre tienen que imitarse de formas que no funcionan bien.
    Por ejemplo, un <select> nativo del navegador puede extenderse más allá de los límites de la ventana del navegador, así que no tienes que preocuparte de que quede recortado por la ventana; en cambio, un select falso y vistoso de un toolkit como Quasar no puede hacerlo, por lo que sus opciones de posicionamiento quedan limitadas.
    Para hacerlo bien, en win32 cada popover debería tener su propio HWND nativo, y en Cocoa/macOS parece que debería estar dentro de su propio NSView.
    Me pregunto si los navegadores actuales realmente lo implementan así, o si simplemente lo dibujan encima dentro de la ventana del navegador.

    • Estos popovers son simplemente nodos DOM normales y se estilizan con CSS normal.
      Si se permitiera que un sitio web dibuje fuera del viewport asignado, salvo casos muy limitados como alert(), confirm() y [title], sería mucho más fácil imitar de forma convincente diálogos del navegador o del sistema operativo.
      Por ejemplo, una página podría imitar el widget de desbloqueo de una extensión de gestor de contraseñas.
      Eso es un gran riesgo de seguridad, y no creo que valga la pena frente a los beneficios limitados.
      No es una preocupación teórica.
      Durante años, los estafadores han creado interfaces falsas muy convincentes, incluidas ventanas emergentes falsas con el chrome del navegador, e incluso se podían arrastrar.
      La imposibilidad de dibujar fuera de los límites del viewport era casi la única restricción que no habían podido esquivar.
    • No sé qué tan útil sería en la práctica una función así.
      En dispositivos pequeños, el navegador web casi siempre cubre toda la pantalla, y aun en monitores grandes normalmente toca al menos una esquina.
    • También parece que sería más fácil detectarlo semánticamente.
      Eso también ayuda a la accesibilidad y a la capacidad de rastreo, y sería útil si alguien quisiera crear un plugin de “bloquear popups”.
    • Firefox técnicamente soporta una función para hacer que parte del contenido de la página “salte” a una ventana a nivel del sistema operativo separada.
      Esta función se expone mediante elementos XUL que solo pueden usarse en [X]HTML privilegiado renderizado por el proceso principal del navegador.
      No creo que ningún desarrollador de navegadores quiera dar a páginas web normales el permiso de crear ventanas del sistema operativo sin bordes.
    • No parece que las apps web vayan a obtener pronto una integración con el sistema de ventanas nativo como la que se imagina.
      Que algunos controles estándar se comporten así es un efecto secundario de implementación específico de cada OS, porque están implementados de forma nativa en el sistema operativo, y no es obligatorio implementarlos de esa manera.
  • Los navegadores tienen bloqueadores de pop-ups integrados, así que resulta un poco gracioso que creen una API como esta
    Sé que hay una diferencia, pero aun así
    Tengo edad suficiente para recordar las guerras de pop-ups/pop-unders de fines de los 90 y principios de los 2000
    Creo que ganamos esa batalla, pero la guerra por nuestra atención todavía tiene mucho camino por delante

    • Creo que estás comparando cosas distintas
      Un popover es un elemento flotante que muestra información contextual cuando hace falta
      Lo que mencionas es algo completamente distinto
    • Entiendo lo que quieres decir, pero en realidad no parecen ser comparables
      Los pop-ups llenan el sistema operativo de ventanas basura y, en el peor de los casos, impiden usar la computadora
      Un cuadro de diálogo popover se termina cerrando la pestaña
      Este estilo de popover es bastante útil para mostrar información y se viene usando desde hace mucho
      Puede usarse de forma molesta, pero como los modales, también tiene muchos casos de uso reales
    • Se ve mucho esta reacción, pero no tiene mucho sentido
      Hoy también se pueden implementar popovers con div existentes, etc.
      Ej.: https://getbootstrap.com/docs/5.3/components/popovers/
      Lo que cambia es que se pueden implementar popovers sin una biblioteca adicional medio mágica
      Aunque bloquees un elemento explícito “popover”, la gente seguirá usando bibliotecas personalizadas
    • Esto no es un pop-up
      La gente odia los pop-ups porque son intrusivos y tienen una ventana separada
      Esta API reemplaza los modales con div y reduce el tiempo y código de los desarrolladores
    • La implementación original de los pop-ups rompe el límite entre el contenido de la aplicación y el sistema operativo, y los bloqueadores de pop-ups intentan impedir eso
      Esta API no rompe ese límite
      Si ese límite se rompe, la usabilidad y la seguridad del sistema empeoran, así que no es el camino deseado
  • Dicen: “Los popovers creados con la Popover API siempre son no modales. Si quieres crear un popover modal, el elemento <dialog> es lo correcto”, pero no entiendo por qué
    Este es un caso de uso válido para los popovers
    Sobre todo si al abrirse se difumina el fondo; y si un botón difuminado puede terminar recibiendo un clic accidental del usuario, me pregunto por qué ofrecen esa función
    Al buscarlo, vi que se pueden combinar ambos
    Algo como: “Si quieres combinar el control de popover con la semántica de diálogo, puedes convertir un elemento <dialog> en popover”
    Entonces me parece que aquí tendría más sentido un atributo como modal
    Porque están reconociendo claramente el caso de uso

    • Probablemente una de varias razones sea que <dialog> existe desde mucho antes
  • Muy bueno
    Si lo entendí bien, más que introducir una función nueva, parece simplificar lo que antes requería un div modal, un div de máscara, un div contenedor y CSS incómodo para posicionamiento
    También se agregan pseudoclases que facilitan el styling, me gusta

    • También permite usar la funcionalidad básica sin JavaScript
      No hace falta forzar el uso de un checkbox oculto
      No sé hasta dónde se podrá llegar sin JS con popovers con styling y animaciones, pero es bueno tener soporte sin JS con manejo correcto del foco
      Quisiera decir que el soporte de accesibilidad también viene incorporado, pero no lo encuentro en la especificación actual
      Si también se encargara de anunciar el elemento a herramientas de accesibilidad como lectores de pantalla, sería de gran ayuda
      Porque al hacerlo manualmente es bastante fácil olvidarlo
    • Esta API permite controlar desde el DOM el estado de visibilidad del elemento popover incluso sin JavaScript
      Definitivamente es útil
  • Demo: https://mdn.github.io/dom-examples/popover-api

    • En la demo de popovers anidados no se puede mover en diagonal de Pizza a Ham
      Porque nadie implementó en Chrome ni Firefox el tiempo de espera antes de que desaparezca el submenú
      Décadas de investigación en experiencia de usuario desaparecieron y, casi como era de esperarse
      https://mdn.github.io/dom-examples/popover-api/nested-popove...
    • Según la tabla de compatibilidad de navegadores debería funcionar, pero parece que no anda en iOS Safari
  • Se ve genial, pero no entiendo por qué esta página no tiene ni una imagen que muestre qué es un popover

  • Excelente
    Una implementación personalizada hecha con Stimulus usando Popper está aquí
    https://github.com/tramlinehq/tramline/blob/main/app/javascr...
    Y la implementación para diálogos está aquí
    https://github.com/tramlinehq/tramline/blob/main/app/javascr...