Product Craft Bible
State Machines
Inicio Animación y Motion State Machines
Animación y Motion

State Machines

3 reglas investigación 2026
42

State Machines

3 reglas
405

Ciclo idle → loading → success → error

Todo componente asíncrono debe modelar cuatro estados mínimos: idle (acción disponible), loading (en progreso), success (confirmación breve) y error (recuperable). Omitir cualquiera deja al usuario sin orientación. El ciclo debe ser completo y cerrado: desde error siempre hay un camino de vuelta a idle.

investigación 2026
Preferir
idle botón disponible
loading deshabilitado para evitar doble cobro
success regresa a idle tras 3s
Pago confirmado
Ref: TXN-4829 · $249.00 MXN
error CTA que regresa a idle
No se pudo procesar el pago
Tarjeta rechazada · sin cargo realizado
406

Botón de 5 estados

Un botón completo tiene cinco estados distintos: default (listo), hover (feedback inmediato), active (presionado), disabled (bloqueado con motivo) y loading (acción en curso). Cada estado comunica algo diferente y previene doble envío.

investigación 2026
Preferir
Plan Profesional
$299 MXN/mes · cancela cuando quieras
Default
Hover
Active
Disabled
Llena los datos de pago primero
Loading
El estado disabled explica el motivo, el loading desactiva el botón para prevenir doble cobro
407

data-state como fuente de verdad CSS

Usar data-state como atributo único en el DOM evita clases colisionantes y hace que CSS sea la capa exclusiva de presentación. Un solo cambio de atributo en JS activa todas las transiciones asociadas. El patrón [data-state="loading"] es predecible, testeable y accesible.

investigación 2026
Preferir
<button data-state="idle">
[data-state="idle"] { background: var(--accent); color:#fff; }
[data-state="loading"] { background: color-mix(in srgb,var(--accent) 70%,#000); cursor:wait; }
[data-state="success"] { background: #16a34a; }
[data-state="error"] { background: #dc2626; }
Evitar
// Al guardar:
btn.classList.add('loading');
btn.classList.remove('idle');
// Al fallar:
btn.classList.add('disabled');
btn.classList.remove('loading');
// Si falta el remove()...
Estado imposible detectado:
class="btn idle loading disabled"
// 3 estados activos simultaneamente