Product Craft Bible
Interacción
Inicio Animación y Motion Interacción
Animación y Motion

Interacción

10 reglas jakub.kr · hobday · matthewstromhobdayrauno.mehobday · littlebigdetails
27

Interacción

10 reglas
296

Alineación óptica, no geométrica

El ojo humano no percibe el centro geométrico como centro visual, especialmente con formas asimetricas (play, flechas). Ajustar padding/margin visualmente. No hay propiedad CSS automática, requiere juicio visual.

jakub.kr · hobday · matthewstrom
Preferir
+3px
Reproducir video margin-left: 3px compensa asimetria
Evitar
Reproducir video Centro geometrico: play se ve desplazado
297

Íconos con texto: bajar contraste del ícono

Los íconos tienen formas rellenas que pesan más visualmente que el texto por píxel. Si el texto es #333, poner el ícono a opacity: 0.6 o un fill más claro como #777.

hobday
Preferir
Inicio
Equipo
Ajustes
Evitar
Inicio
Equipo
Ajustes
298

Tres estados visuales por elemento interactivo

Cada elemento interactivo necesita: default, hover y active. Hover: cambio de background/color sutil. Active: transform: scale(0.96-0.97) para feedback tactil. Focus-visible: outline: 2px solid con outline-offset: 2px.

rauno.me
Preferir
4 estados diferenciados
Guardar
default
Guardar
hover
Guardar
active
Guardar
focus
Evitar
Un solo estado para todo
Guardar
default
Guardar
hover?
Guardar
active?
Guardar
focus?
299

Fitts's Law: explotar esquinas y bordes

Las esquinas de pantalla son targets infinitos (el cursor no puede sobrepasarlas). Posicionar controles frecuentes en esquinas. Min touch target: 20px, recomendado 36px para icon buttons. border-radius: 9999px maximiza hit área en pills.

rauno.me
Preferir
36px
36px
Publicar
pill 9999px
Evitar
20px
20px
Publicar
20px
300

Generous mouse paths en menús anidados

Cuando el cursor se mueve de un item de menú padre hacia un submenu hijo, crear un "corredor" invisible que permita al cursor cruzar sin que el submenu se cierre prematuramente.

hobday
Preferir
Archivo
Editar
Ver
Copiar
Pegar
Deshacer
Corredor triangular mantiene submenu abierto
Evitar
Archivo
Editar
Ver
Copiar
Pegar
Deshacer
Sin corredor: submenu se cierra al cruzar gap
301

Menús abren instantaneo, cierran con fade lento

La apertura debe ser inmediata (el usuario ya decidio). El cierre puede tener un breve fade-out que da oportunidad de cancelar la salida accidental.

hobday
Preferir
Menú
Editar perfil
Configuración
Cerrar sesión
open: 0ms instant · close: 200ms fade
Evitar
Menú
Editar perfil
Configuración
Cerrar sesión
open: 300ms ease-in · close: 0ms
302

Nunca perder información ingresada

Si el usuario navega fuera de un formulario, guardar el estado. Si la conexión se cae en un chat, copiar el texto no enviado. Si un modal se cierra accidentalmente, preservar el contenido del draft.

hobday · littlebigdetails
Preferir
Nuevo mensaje
Para
maria@empresa.com
Asunto
Propuesta Q3 actualizada
Mensaje
Adjunto la versión revisada con los cambios que comentamos en la junta del...
Draft guardado. Puedes volver cuando quieras.
Evitar
Nuevo mensaje
Para
Asunto
Mensaje
Navegaste fuera. Todo tu texto se perdio.
303

Focus states con doble box-shadow

El anillo de foco con outline a veces se corta en bordes redondeados o queda pegado al borde del elemento. La alternativa elegante es usar box-shadow en dos capas: primero un ring del color de fondo para crear separación, luego el ring de acento.

hobday · inclusive-components
Preferir
Doble box-shadow
Email
usuario@empresa.com
Nombre
Carlos Mendez
Enviar
2px gap entre elemento y anillo de foco
Evitar
Outline pegado
Email
usuario@empresa.com
Nombre
Carlos Mendez
Enviar
outline-offset:0 se funde con el borde
304

Data attributes para variantes de componentes

En lugar de concatenar classNames condicionalmente, usar data-variant o data-state como atributo y targetearlo en CSS con [data-variant='primary']. El HTML resulta más legible, el CSS más explicito y los estilos no dependen de la lógica de strings del componente.

emilkowalski · rauno.me
Preferir
data-variant en HTML
Guardar
Cancelar
Eliminar
<button class="btn" data-variant="primary"> <button class="btn" data-variant="secondary"> <button class="btn" data-variant="danger">
Fácil de inspeccionar CSS explicito
Evitar
Concatenación de clases
Guardar
Cancelar
Eliminar
const cls = ['btn', variant === 'primary' ? 'btn-primary' : '', size === 'lg' ? 'btn-lg' : '', ].join(' ');
Propenso a espacios Fragil
305

Container queries para widgets independientes

Los media queries responden al viewport, no al contenedor del componente. Un widget en un sidebar angosto necesita un layout diferente al mismo widget en el área principal, aunque el viewport sea el mismo. container-type: inline-size hace el componente verdaderamente portable.

emilkowalski · refactoring ui
Preferir
Área principal (ancho)
Ana Martinez Disenadora senior
Activo
Sidebar (angosto)
Ana M.
Activo
Evitar
Área principal (ancho)
Ana Martinez Disenadora senior
Activo
Sidebar (angosto)
Ana Martinez Disenad...