Consigna y contexto aplicable
Necesitas un botón de configuración que abra un diálogo y lo cierre sin duplicar la sincronización del estado del componente. Explica cómo command y commandfor crean un control declarativo, incluidos comandos personalizados, accesibilidad por teclado y compatibilidad para navegadores más antiguos.
La API Invoker Commands permite que un botón apunte al ID de un elemento e invoque una acción integrada o despache un evento command personalizado. Expresa quién invoca y qué elemento actúa en HTML, pero no reemplaza las máquinas de estado de negocio, las verificaciones de permisos ni las alternativas de respaldo para navegadores no compatibles.
Qué evalúa el entrevistador
Cubre el requisito de que el destino esté en el mismo árbol para commandfor, comandos integrados frente a personalizados, cancelación de eventos y comportamiento predeterminado, gestión de teclado y foco, y mejora progresiva en lugar de tratar un nuevo atributo como la única garantía en tiempo de ejecución.
Preguntas de clarificación
Confirma si el destino es un diálogo modal, un popover no modal o un elemento ordinario; si el botón y el destino comparten el mismo árbol; si se requiere validación de envío; y qué navegadores son relevantes. También aclara el foco inicial, el comportamiento de Escape, el retorno del foco y si los comandos personalizados necesitan autorización de negocio.
Estructura de respuesta de 30 segundos
“Apuntaría commandfor al destino y usaría comandos integrados para mostrar, ocultar o alternar. Las acciones de negocio usan un evento de comando personalizado donde un controlador valida el estado y puede prevenir el comportamiento predeterminado. Los botones nativos son accesibles por teclado, pero aun así verificaría la entrada de foco, Escape, el retorno del foco y los nombres accesibles. Los navegadores antiguos conservan un respaldo de JavaScript o de componente que llama a la misma máquina de estados, de modo que las rutas nativas y de respaldo permanezcan equivalentes.”
Análisis detallado paso a paso
Paso 1: Declarar la relación de botón a destino
El valor de commandfor es el ID del elemento de destino, y ambos elementos deben estar en el mismo árbol. El valor de command del botón elige la acción. Por lo tanto, el HTML estático puede expresar control sin consultas manuales ni sincronización de estado duplicada.
Paso 2: Preferir comandos integrados
Los diálogos y popovers definen comandos del navegador para mostrar, ocultar y alternar. El comportamiento nativo puede cooperar con las reglas de capa superior (top-layer), cierre ligero (light-dismiss) y foco. No reimplementes una semántica existente con una cadena personalizada.
<button commandfor="settings" command="show-modal">
Open settings
</button>
<dialog id="settings">
<button commandfor="settings" command="close">Close</button>
</dialog>Paso 3: Manejar eventos de comando personalizados
Los comandos personalizados que comienzan con -- despachan un evento command que contiene el destino y el valor del comando. El manejador debe validar el origen y el estado actual, llamar a preventDefault() cuando sea necesario y ejecutar la acción de negocio. Un comando personalizado no cambia automáticamente la visibilidad.
Paso 4: Mantener la autorización y la validación en el código de negocio
La invocación declarativa expresa intención; no puede eludir la autorización, la validación de formularios ni la persistencia asíncrona. Un controlador de destino debe verificar permisos, versión de datos y estado actual antes de actuar, y devolver un error recuperable en lugar de tratar a HTML como un límite de seguridad.
Paso 5: Diseñar el comportamiento del foco y del teclado
Para diálogos y popovers nativos, verifica el foco inicial, el cierre con Escape, el retorno del foco y el nombre accesible. Los elementos ordinarios no adquieren estas semánticas automáticamente. Un destino personalizado necesita un modelo de teclado y una política de foco explícitos.
Paso 6: Manejar la cancelación y las condiciones de carrera
Varios botones pueden emitir comandos al mismo tiempo. Verifica el estado actual del destino para evitar aperturas duplicadas, envíos repetidos o reaperturas asíncronas obsoletas tras el cierre. Mantén el estado de negocio asíncrono separado del estado visible para que los fallos no puedan dejar un estado de ARIA o de foco incorrecto.
Paso 7: Proporcionar una alternativa para navegadores antiguos
Los navegadores que no admiten commandfor ignoran los atributos, por lo que se debe conservar un listener de botón normal o un enlace de componente. Reutiliza el mismo manejador de comandos y pruebas de accesibilidad en lugar de mantener dos comportamientos divergentes.
Paso 8: Probar las rutas nativas y de respaldo
Prueba con ratón, teclado, lector de pantalla, Escape, retorno del foco, comandos duplicados, valores predeterminados cancelados, permisos denegados y fallos asíncronos. Usa una matriz de navegadores para comandos integrados, eventos personalizados y tipos de destino; una etiqueta MDN Baseline no es una garantía para todos los entornos de ejecución.
Respuesta de muestra de alta calidad
Apuntaría un botón estático con commandfor a un diálogo en el mismo árbol y usaría los comandos integrados show-modal y close para el comportamiento básico. La lógica de negocio usaría un evento de comando personalizado cuyo manejador comprueba autorización, versión del formulario y estado actual, pudiendo prevenir el comportamiento predeterminado; el comando personalizado en sí no alterna la visibilidad. El diálogo nativo proporciona semántica modal, pero aun así probaría el foco, Escape, el retorno del foco y el nombre accesible. Los navegadores antiguos ignoran los nuevos atributos, por lo que un listener de respaldo llama al mismo manejador de comandos. Finalmente, probaría el comportamiento con teclado y lector de pantalla, clics concurrentes, fallos asíncronos y una matriz de navegadores en ambas rutas.
Errores comunes
Asumir que commandfor busca a través de un Shadow DOM o documento
La especificación requiere el ID de destino en el mismo árbol. El control entre árboles o entre documentos necesita un protocolo de componentes o mensajería explícitos, no un ID diferente.
Asumir que cada comando personalizado tiene un comportamiento predeterminado
Los comandos personalizados principalmente despachan un evento. El manejador debe implementar el cambio de estado y definir cuándo se cancela el comportamiento predeterminado.
Probar únicamente clics de ratón
La accesibilidad por teclado, el orden del foco, Escape y la retroalimentación del lector de pantalla son parte del contrato de interacción. Un estado abierto visual no es evidencia completa de accesibilidad.
Preguntas de seguimiento y respuestas
¿Un reemplazo dinámico del destino requiere volver a vincular commandfor?
Si el reemplazo mantiene el mismo ID y permanece en el mismo árbol, la relación declarativa puede continuar. El controlador todavía debe restablecer el foco y el estado de negocio. Los IDs duplicados o un destino ausente deben bloquear el comando y exponer un estado diagnosticable.
¿Cómo se evitan envíos duplicados a partir de un comando asíncrono personalizado?
Usa el estado de la solicitud o una clave de idempotencia para bloquear la misma acción, marca el botón como ocupado y mantén una ruta de cancelación o reintento. Tras completarse, confirma que el destino aún existe para que un resultado antiguo no pueda mutar una nueva sesión.
¿Cuándo debería mantenerse un componente de JavaScript en lugar de usar únicamente comandos HTML?
Usa un componente cuando la interacción requiera coordinación entre árboles, animaciones complejas, máquinas de estado asíncronas o soporte amplio para navegadores heredados. command aún puede ser un punto de entrada para mejora progresiva, pero el límite de negocio debe seguir siendo comprobable.