Chrome introduce `command` y `commandfor` en botones a partir de la versión 135
(developer.chrome.com)- Los botones son esenciales para crear aplicaciones web dinámicas. Se usan para abrir menús, cambiar acciones y enviar formularios
- En Chrome 135, los nuevos atributos
commandycommandformejoran y reemplazan los atributos anteriorespopovertargetactionypopovertarget - Problemas que suelen aparecer al implementar el comportamiento de botones:
- Los manejadores
onclickde HTML pueden tener un uso limitado en código real debido a políticas de seguridad (CSP) - Es necesario sincronizar el estado entre el botón y otros elementos, y el código para gestionar ese estado manteniendo la accesibilidad es complejo
- Incluso en React, AlpineJS y Svelte, el manejo de estado y eventos también es complejo
- Los manejadores
Patrón command y commandfor
- Al usar los atributos
commandycommandfor, un botón puede actuar de forma declarativa sobre otro elemento. Esto ofrece la comodidad de un framework sin perder flexibilidad - El botón
commandforusa un ID (similar al atributofor) ycommandacepta valores integrados para ofrecer un enfoque más intuitivo - Ejemplo: implementar un botón para abrir un menú
- No se necesitan
aria-expandedni JavaScript adicional
<button commandfor="my-menu" command="show-popover"> Open Menu </button> <div popover id="my-menu"> <!-- ... --> </div> - No se necesitan
command y commandfor vs popovertargetaction y popovertarget
- Si ya usaste
popover, puede que conozcas los atributospopovertargetypopovertargetaction - Funcionan de forma similar a
commandforycommand, pero están especializados para popovers - Los nuevos atributos reemplazan por completo a los anteriores y además ofrecen funcionalidad adicional
Comandos integrados
- El atributo
commandincorpora acciones que se mapean a varias APIshow-popover: se mapea ael.showPopover()hide-popover: se mapea ael.hidePopover()toggle-popover: se mapea ael.togglePopover()show-modal: se mapea adialogEl.showModal()close: se mapea adialogEl.close()
- Ejemplo: implementar un diálogo de confirmación de borrado
- Es posible gestionar el estado y la accesibilidad sin JavaScript
<button commandfor="confirm-dialog" command="show-modal"> Delete Record </button> <dialog id="confirm-dialog"> <header> <h1>Delete Record?</h1> <button commandfor="confirm-dialog" command="close" aria-label="Close"> <img role="none" src="/close-icon.svg"> </button> </header> <p>Are you sure? This action cannot be undone</p> <footer> <button commandfor="confirm-dialog" command="close" value="cancel"> Cancel </button> <button commandfor="confirm-dialog" command="close" value="delete"> Delete </button> </footer> </dialog>- Código para procesar el resultado: se puede manejar el valor devuelto en el evento
closedel diálogo
dialog.addEventListener("close", (event) => { if (event.target.returnValue === "cancel") { console.log("Cancel was clicked"); } else if (event.target.returnValue === "delete") { console.log("Delete was clicked"); } });
Comandos personalizados
- Además de los comandos integrados, se pueden definir comandos personalizados usando el prefijo
-- - Los comandos personalizados disparan el evento
"command"en el elemento objetivo, pero no ejecutan lógica adicional - Ejemplo: implementar un comando para rotar una imagen
<button commandfor="the-image" command="--rotate-landscape"> Landscape </button> <button commandfor="the-image" command="--rotate-portrait"> Portrait </button> <img id="the-image" src="photo.jpg"> <script type="module"> const image = document.getElementById("the-image"); image.addEventListener("command", (event) => { if (event.command === "--rotate-landscape") { image.style.rotate = "-90deg"; } else if (event.command === "--rotate-portrait") { image.style.rotate = "0deg"; } }); </script>
Manejo de comandos en Shadow DOM
- En Shadow DOM, como
commandforfunciona con base en ID, existen las siguientes limitaciones:- No es posible referenciar elementos entre distintos Shadow DOM
- En estos casos, se puede usar la API de JavaScript para establecer la propiedad
.commandForElement
- Ejemplo: conectar un comando en Shadow DOM
<my-element> <template shadowrootmode="open"> <button command="show-popover">Show popover</button> <slot></slot> </template> <div popover><!-- ... --></div> </my-element> <script> customElements.define("my-element", class extends HTMLElement { connectedCallback() { const popover = this.querySelector('[popover]'); this.shadowRoot.querySelector('button').commandForElement = popover; } }); </script>
Planes futuros
- En Chrome planean agregar más comandos integrados:
- abrir y cerrar elementos
<details> - soporte del comando
show-pickeren<input>y<select> - comandos de reproducción para
<video>y<audio> - función para copiar texto desde un elemento
- abrir y cerrar elementos
1 comentarios
Opiniones de Hacker News
Los teóricos de los lenguajes de programación han estado especulando desde los años 80 sobre
comefrom, una versión más potente degoto. Solo se implementó en INTERCAL. INTERCAL es superior a lenguajes como C en seguridad, rendimiento y ergonomía, pero ha tenido dificultades para entrar al mercado comercial. Es interesante ver que JavaScript incorpore esta funcionalidad de INTERCAL. Ojalá esto lleve a un auge de la programación cortés, del mismo modo que los objetos basados en closures de JavaScript llevaron la programación funcional al mainstreamInvokers no es algo exclusivo de Chrome. Ya se puede usar también en Firefox Nightly
La idea de implementar comportamiento declarativo de UI sin JS es atractiva
aria-expanded)show-modalincorporan accesibilidad directamente en el marcado--rotate-landscape) permiten que los componentes expongan una API a través de HTMLDudas:
.commandForElemententre distintos shadow roots. Parece un problema resuelto solo a mediasshow-picker,toggle-details), ¿la plataforma terminará inflándose con sintaxis de nicho?Especificación:
button, atributocommandforbutton, atributocommand¿Es este el patrón de acciones/mensajería que usaban Next, Be, Apple y otros hace unos 30 años, o se me está escapando algo?
El toolkit Java de UI temprano de Netscape (IFC) permitía conectar elementos de acción
Los nuevos atributos
commandycommandformejoran y reemplazanpopovertargetactionypopovertargetTengo una reacción completamente alérgica a programar con strings. Entiendo las ventajas de accesibilidad, pero no me entusiasma especialmente usar IDs de elementos como otra capa más de comportamiento para apps web
No debieron haber implementado esto sin una API completa. En vez de unos 5 comandos, parecería que todas las funciones de JavaScript deberían poder implementarse desde HTML. Eso podría terminar siendo miles de comandos
Tenía expectativas de ver command and conquer en HTML
Está bien mejorar y ampliar HTML, pero aún falta mucho camino por recorrer. El equipo de HTMX tiene algunas buenas ideas