Reto: un botón que cambia mientras lo pulsas
El reto #
Crea MiBoton para que muestre su contenido normal sobre fondo negro. Mientras lo mantienes pulsado debe mostrar Me has pulsado sobre fondo rojo. Al soltarlo o cancelar la interacción debe volver a su apariencia normal.
No basta con onClick: un clic representa una activación, mientras que aquí necesitamos distinguir el comienzo y el final de la pulsación.
Solución #
Los eventos de puntero permiten utilizar ratón, lápiz o interacción táctil. Añadimos teclado para que el botón también responda a Espacio y Enter.
1import { useState, type KeyboardEvent, type ReactNode } from 'react'; 2 3interface Props { 4 children: ReactNode; 5} 6 7function MiBoton({ children }: Props) { 8 const [pulsado, setPulsado] = useState(false); 9 10 function handleKeyDown(event: KeyboardEvent<HTMLButtonElement>) { 11 if (event.key === ' ' || event.key === 'Enter') { 12 event.preventDefault(); 13 setPulsado(true); 14 } 15 } 16 17 function handleKeyUp(event: KeyboardEvent<HTMLButtonElement>) { 18 if (event.key === ' ' || event.key === 'Enter') { 19 event.preventDefault(); 20 setPulsado(false); 21 } 22 } 23 24 return ( 25 <button 26 type="button" 27 style={{ backgroundColor: pulsado ? 'red' : 'black', color: 'white' }} 28 onPointerDown={(event) => { 29 if (event.button === 0) setPulsado(true); 30 }} 31 onPointerUp={() => setPulsado(false)} 32 onPointerLeave={() => setPulsado(false)} 33 onPointerCancel={() => setPulsado(false)} 34 onKeyDown={handleKeyDown} 35 onKeyUp={handleKeyUp} 36 onBlur={() => setPulsado(false)} 37 > 38 {pulsado ? 'Me has pulsado' : children} 39 </button> 40 ); 41} 42 43export default function Ejem_09() { 44 return <MiBoton>Púlsame</MiBoton>; 45}
pulsado guarda un booleano. Dos ternarios deciden el color y el texto a partir de ese mismo dato, por lo que ambos cambian juntos.
onPointerLeave restaura el botón si sacas el puntero; onPointerCancel cubre una interacción cancelada por el navegador. onBlur lo restaura si pierde el foco. El filtro button === 0 acepta el botón principal del ratón.
Si solo practicas con ratón, puedes empezar con onMouseDown, onMouseUp y onMouseLeave, como en el ejemplo inicial. La versión con puntero amplía los dispositivos admitidos.
Comprueba tu solución #
Mantén pulsado y suelta, sal del botón manteniendo la pulsación y prueba Tab seguido de Espacio o Enter. Al terminar cada interacción debe recuperar el contenido original. Este ejercicio muestra un estado momentáneo; no es un botón de alternancia que permanezca activado tras el clic.
Cuestionario del tema #
Abre el cuestionario en las actividades de este tema para comprobar lo aprendido. Cada respuesta incluye una explicación.